diff --git a/subgraph/core/schema.graphql b/subgraph/core/schema.graphql
index dc34b33b3..903c967d1 100644
--- a/subgraph/core/schema.graphql
+++ b/subgraph/core/schema.graphql
@@ -69,6 +69,7 @@ interface Evidence {
type User @entity {
id: ID! # address
+ userAddress: String!
tokens: [JurorTokensPerCourt!]! @derivedFrom(field: "juror")
totalStake: BigInt!
totalDelayed: BigInt!
@@ -237,6 +238,7 @@ type Counter @entity {
casesVoting: BigInt!
casesRuled: BigInt!
casesAppealing: BigInt!
+ totalLeaderboardJurors: BigInt!
}
type FeeToken @entity {
diff --git a/subgraph/core/src/KlerosCore.ts b/subgraph/core/src/KlerosCore.ts
index e6c06a354..187b292ca 100644
--- a/subgraph/core/src/KlerosCore.ts
+++ b/subgraph/core/src/KlerosCore.ts
@@ -18,7 +18,13 @@ import { createCourtFromEvent } from "./entities/Court";
import { createDisputeKitFromEvent, filterSupportedDisputeKits } from "./entities/DisputeKit";
import { createDisputeFromEvent } from "./entities/Dispute";
import { createRoundFromRoundInfo, updateRoundTimeline } from "./entities/Round";
-import { updateCases, updateCasesAppealing, updateCasesRuled, updateCasesVoting } from "./datapoint";
+import {
+ updateCases,
+ updateCasesAppealing,
+ updateCasesRuled,
+ updateCasesVoting,
+ updateTotalLeaderboardJurors,
+} from "./datapoint";
import { addUserActiveDispute, computeCoherenceScore, ensureUser } from "./entities/User";
import { updateJurorStake } from "./entities/JurorTokensPerCourt";
import { createDrawFromEvent } from "./entities/Draw";
@@ -139,13 +145,23 @@ export function handleNewPeriod(event: NewPeriod): void {
const draw = Draw.load(draws[j].id);
if (!draw) continue;
+ const juror = ensureUser(draw.juror);
+ juror.totalResolvedVotes = juror.totalResolvedVotes.plus(ONE);
+
+ // Increment totalLeaderboardJurors in the Counter entity if this is the first resolved vote for the juror
+ if (juror.totalResolvedVotes.equals(ONE)) {
+ updateTotalLeaderboardJurors(ONE, event.block.timestamp);
+ }
+
// Since this is a ClassicVote entity, this will only work for the Classic DisputeKit (which has ID "1").
const vote = ClassicVote.load(`${round.disputeKit}-${draw.id}`);
- if (!vote) continue;
-
- const juror = ensureUser(draw.juror);
- juror.totalResolvedVotes = juror.totalResolvedVotes.plus(ONE);
+ if (!vote) {
+ // Recalculate coherenceScore
+ juror.coherenceScore = computeCoherenceScore(juror.totalCoherentVotes, juror.totalResolvedVotes);
+ juror.save();
+ continue;
+ }
if (vote.choice === null) continue;
@@ -155,9 +171,7 @@ export function handleNewPeriod(event: NewPeriod): void {
}
// Recalculate coherenceScore
- if (juror.totalResolvedVotes.gt(ZERO)) {
- juror.coherenceScore = computeCoherenceScore(juror.totalCoherentVotes, juror.totalResolvedVotes);
- }
+ juror.coherenceScore = computeCoherenceScore(juror.totalCoherentVotes, juror.totalResolvedVotes);
juror.save();
}
diff --git a/subgraph/core/src/datapoint.ts b/subgraph/core/src/datapoint.ts
index 2b098c64c..7ddc149ce 100644
--- a/subgraph/core/src/datapoint.ts
+++ b/subgraph/core/src/datapoint.ts
@@ -15,6 +15,7 @@ const VARIABLES = [
"casesVoting",
"casesRuled",
"casesAppealing",
+ "totalLeaderboardJurors",
];
function updateDataPoint(delta: BigInt, timestamp: BigInt, variable: string): void {
@@ -43,6 +44,7 @@ function checkFirstDayActivity(): void {
counter.casesVoting = ZERO;
counter.casesRuled = ZERO;
counter.casesAppealing = ZERO;
+ counter.totalLeaderboardJurors = ZERO;
counter.save();
}
}
@@ -86,3 +88,7 @@ export function updateCasesRuled(delta: BigInt, timestamp: BigInt): void {
export function updateCasesAppealing(delta: BigInt, timestamp: BigInt): void {
updateDataPoint(delta, timestamp, "casesAppealing");
}
+
+export function updateTotalLeaderboardJurors(delta: BigInt, timestamp: BigInt): void {
+ updateDataPoint(delta, timestamp, "totalLeaderboardJurors");
+}
diff --git a/subgraph/core/src/entities/User.ts b/subgraph/core/src/entities/User.ts
index f038ad5ac..95651dc32 100644
--- a/subgraph/core/src/entities/User.ts
+++ b/subgraph/core/src/entities/User.ts
@@ -27,6 +27,7 @@ export function ensureUser(id: string): User {
export function createUserFromAddress(id: string): User {
const user = new User(id);
+ user.userAddress = id.toLowerCase();
user.totalStake = ZERO;
user.totalDelayed = ZERO;
user.activeDisputes = ZERO;
diff --git a/subgraph/package.json b/subgraph/package.json
index d82f9c5be..de6899c48 100644
--- a/subgraph/package.json
+++ b/subgraph/package.json
@@ -1,6 +1,7 @@
{
"name": "@kleros/kleros-v2-subgraph",
- "version": "0.10.1",
+ "version": "0.10.3",
+ "drtVersion": "0.11.0",
"license": "MIT",
"scripts": {
"update:core:arbitrum-sepolia-devnet": "./scripts/update.sh arbitrumSepoliaDevnet arbitrum-sepolia core/subgraph.yaml",
@@ -11,9 +12,9 @@
"build:core": "graph build --output-dir core/build/ core/subgraph.yaml",
"test:core": "cd core && graph test",
"clean:core": "graph clean --codegen-dir core/generated/ --build-dir core/build/ ; rm core/subgraph.yaml.bak.*",
- "deploy:core:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-core-devnet -l v$npm_package_version core/subgraph.yaml",
- "deploy:core:arbitrum-sepolia": "graph deploy --product subgraph-studio kleros-v2-core-testnet -l v$npm_package_version core/subgraph.yaml",
- "deploy:core:arbitrum": "graph deploy --product subgraph-studio kleros-v2-core-mainnet -l v$npm_package_version core/subgraph.yaml",
+ "deploy:core:arbitrum-sepolia-devnet": "graph deploy kleros-v2-core-devnet -l v$npm_package_version core/subgraph.yaml",
+ "deploy:core:arbitrum-sepolia": "graph deploy kleros-v2-core-testnet -l v$npm_package_version core/subgraph.yaml",
+ "deploy:core:arbitrum": "graph deploy kleros-v2-core-mainnet -l v$npm_package_version core/subgraph.yaml",
"deploy:core:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-core-local --version-label v$(date +%s) core/subgraph.yaml",
"rebuild-deploy:core:local": "yarn update:core:local && yarn codegen:core && yarn build:core && yarn create:local kleros/kleros-v2-core-local && yarn deploy:core:local",
"": "------------------------------------------------------------------------------------------",
@@ -24,8 +25,8 @@
"build:core-neo": "graph build --output-dir core-neo/build/ core-neo/subgraph.yaml",
"test:core-neo": "cd core-neo && graph test",
"clean:core-neo": "graph clean --codegen-dir core-neo/generated/ --build-dir core-neo/build/ ; rm core-neo/subgraph.yaml.bak.*",
- "deploy:core-neo:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-coreneo-devnet -l v$npm_package_version core-neo/subgraph.yaml",
- "deploy:core-neo:arbitrum": "graph deploy --product subgraph-studio kleros-v2-coreneo -l v$npm_package_version core-neo/subgraph.yaml",
+ "deploy:core-neo:arbitrum-sepolia-devnet": "graph deploy kleros-v2-coreneo-devnet -l v$npm_package_version core-neo/subgraph.yaml",
+ "deploy:core-neo:arbitrum": "graph deploy kleros-v2-coreneo -l v$npm_package_version core-neo/subgraph.yaml",
"deploy:core-neo:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-coreneo-local --version-label v$(date +%s) core-neo/subgraph.yaml",
"rebuild-deploy:core-neo:local": "yarn update:core-neo:local && yarn codegen:core-neo && yarn build:core-neo && yarn create:local kleros/kleros-v2-coreneo-local && yarn deploy:core-neo:local",
"-": "------------------------------------------------------------------------------------------",
@@ -35,7 +36,7 @@
"build:core-university": "graph build --output-dir core-university/build/ core-university/subgraph.yaml",
"test:core-university": "cd core-university && graph test",
"clean:core-university": "graph clean --codegen-dir core-university/generated/ --build-dir core-university/build/ ; rm core-university/subgraph.yaml.bak.*",
- "deploy:core-university:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-coreuni-devnet -l v$npm_package_version core-university/subgraph.yaml",
+ "deploy:core-university:arbitrum-sepolia-devnet": "graph deploy kleros-v2-coreuni-devnet -l v$npm_package_version core-university/subgraph.yaml",
"deploy:core-university:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-coreuni-local --version-label v$(date +%s) core-university/subgraph.yaml",
"rebuild-deploy:core-university:local": "yarn update:core-university:local && yarn codegen:core-university && yarn build:core-university && yarn create:local kleros/kleros-v2-coreuni-local && yarn deploy:core-university:local",
"--": "-----------------------------------------------------------------------------------------",
@@ -47,9 +48,9 @@
"build:drt": "graph build --output-dir dispute-template-registry/generated/ dispute-template-registry/subgraph.yaml",
"test:drt": "cd dispute-template-registry && graph test ",
"clean:drt": "graph clean --codegen-dir dispute-template-registry/generated/ --build-dir dispute-template-registry/build/ ; rm dispute-template-registry/subgraph.yaml.bak.*",
- "deploy:drt:arbitrum-sepolia-devnet": "graph deploy --product subgraph-studio kleros-v2-drt-arbisep-devnet -l v$npm_package_version dispute-template-registry/subgraph.yaml",
- "deploy:drt:arbitrum-sepolia": "graph deploy --product subgraph-studio kleros-v2-drt-arbisep-testnet -l v$npm_package_version dispute-template-registry/subgraph.yaml",
- "deploy:drt:arbitrum": "graph deploy --product subgraph-studio kleros-v2-drt -l v$npm_package_version dispute-template-registry/subgraph.yaml",
+ "deploy:drt:arbitrum-sepolia-devnet": "graph deploy kleros-v2-drt-arbisep-devnet -l v$(jq -r .drtVersion $npm_package_json) dispute-template-registry/subgraph.yaml",
+ "deploy:drt:arbitrum-sepolia": "graph deploy kleros-v2-drt-arbisep-testnet -l v$(jq -r .drtVersion $npm_package_json) dispute-template-registry/subgraph.yaml",
+ "deploy:drt:arbitrum": "graph deploy kleros-v2-drt -l v$(jq -r .drtVersion $npm_package_json) dispute-template-registry/subgraph.yaml",
"deploy:drt:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/kleros-v2-drt-local --version-label v$(date +%s) dispute-template-registry/subgraph.yaml",
"rebuild-deploy:drt:local": "yarn update:drt:local && yarn codegen:drt && yarn build:drt && yarn create:local kleros/kleros-v2-drt-local && yarn deploy:drt:local",
"---": "----------------------------------------------------------------------------------------",
diff --git a/web/README.md b/web/README.md
index aa151f2b6..e6b643337 100644
--- a/web/README.md
+++ b/web/README.md
@@ -1,5 +1,5 @@
- Kleros Court v2
+ Kleros Court v2
diff --git a/web/src/app.tsx b/web/src/app.tsx
index f55365693..7fc3b8af8 100644
--- a/web/src/app.tsx
+++ b/web/src/app.tsx
@@ -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"));
@@ -64,10 +65,18 @@ const App: React.FC = () => {
}
/>
}>
-
+
+
+ }
+ />
+ }>
+
}
/>
diff --git a/web/src/assets/svgs/icons/ranking.svg b/web/src/assets/svgs/icons/ranking.svg
new file mode 100644
index 000000000..fb06f2bc0
--- /dev/null
+++ b/web/src/assets/svgs/icons/ranking.svg
@@ -0,0 +1,3 @@
+
diff --git a/web/src/components/BlueIconTextButtonContainer.tsx b/web/src/components/BlueIconTextButtonContainer.tsx
new file mode 100644
index 000000000..31b0f0901
--- /dev/null
+++ b/web/src/components/BlueIconTextButtonContainer.tsx
@@ -0,0 +1,24 @@
+import styled from "styled-components";
+import { hoverShortTransitionTiming } from "styles/commonStyles";
+
+export const BlueIconTextButtonContainer = styled.div`
+ ${hoverShortTransitionTiming}
+ display: flex;
+ align-items: center;
+ font-size: 14px;
+ font-weight: 400;
+ gap: 8px;
+ cursor: pointer;
+ color: ${({ theme }) => theme.primaryBlue};
+
+ svg path {
+ fill: ${({ theme }) => theme.primaryBlue};
+ }
+
+ &:hover {
+ color: ${({ theme }) => theme.secondaryBlue};
+ svg path {
+ fill: ${({ theme }) => theme.secondaryBlue};
+ }
+ }
+`;
diff --git a/web/src/components/EvidenceCard.tsx b/web/src/components/EvidenceCard.tsx
index 3833316dc..07c4bb955 100644
--- a/web/src/components/EvidenceCard.tsx
+++ b/web/src/components/EvidenceCard.tsx
@@ -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";
@@ -224,7 +223,7 @@ const EvidenceCard: React.FC = ({
description,
fileURI,
}) => {
- const dashboardLink = `/dashboard/1/desc/all?address=${sender}`;
+ const profileLink = `/profile/1/desc/all?address=${sender}`;
const transactionExplorerLink = useMemo(() => {
return getTxnExplorerLink(transactionHash ?? "");
@@ -249,7 +248,7 @@ const EvidenceCard: React.FC = ({
-
+
{shortenAddress(sender)}
diff --git a/web/src/components/ExtraStatsDisplay.tsx b/web/src/components/ExtraStatsDisplay.tsx
index dd292164b..37c82cc9b 100644
--- a/web/src/components/ExtraStatsDisplay.tsx
+++ b/web/src/components/ExtraStatsDisplay.tsx
@@ -8,7 +8,13 @@ import { InternalLink } from "./InternalLink";
const Container = styled.div`
display: flex;
gap: 8px;
- align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+`;
+
+const TitleContainer = styled.div`
+ display: flex;
+ gap: 8px;
`;
const SVGContainer = styled.div`
@@ -22,12 +28,12 @@ const SVGContainer = styled.div`
}
`;
-const TextContainer = styled.div`
+const ContentContainer = styled.div`
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
- justify-content: center;
+ text-align: center;
`;
const StyledInternalLink = styled(InternalLink)`
@@ -49,9 +55,11 @@ export interface IExtraStatsDisplay {
const ExtraStatsDisplay: React.FC = ({ title, courtId, text, content, icon: Icon, ...props }) => {
return (
- {}
-
+
+ {}
+
+
{content ? (
content
) : (
@@ -59,7 +67,7 @@ const ExtraStatsDisplay: React.FC = ({ title, courtId, text,
{!isUndefined(text) ? text : }
)}
-
+
);
};
diff --git a/web/src/components/HowItWorks.tsx b/web/src/components/HowItWorks.tsx
index ad4847d60..28e3f1707 100644
--- a/web/src/components/HowItWorks.tsx
+++ b/web/src/components/HowItWorks.tsx
@@ -1,31 +1,8 @@
import React from "react";
-import styled from "styled-components";
-
-import { hoverShortTransitionTiming } from "styles/commonStyles";
import BookOpenIcon from "svgs/icons/book-open.svg";
-const Container = styled.div`
- ${hoverShortTransitionTiming}
- display: flex;
- align-items: center;
- font-size: 14px;
- font-weight: 400;
- gap: 8px;
- cursor: pointer;
- color: ${({ theme }) => theme.primaryBlue};
-
- svg path {
- fill: ${({ theme }) => theme.primaryBlue};
- }
-
- &:hover {
- color: ${({ theme }) => theme.secondaryBlue};
- svg path {
- fill: ${({ theme }) => theme.secondaryBlue};
- }
- }
-`;
+import { BlueIconTextButtonContainer } from "./BlueIconTextButtonContainer";
interface IHowItWorks {
isMiniGuideOpen: boolean;
@@ -36,10 +13,10 @@ interface IHowItWorks {
const HowItWorks: React.FC = ({ isMiniGuideOpen, toggleMiniGuide, MiniGuideComponent }) => {
return (
<>
-
+
How it works
-
+
{isMiniGuideOpen && }
>
);
diff --git a/web/src/components/JurorsLeaderboardButton.tsx b/web/src/components/JurorsLeaderboardButton.tsx
new file mode 100644
index 000000000..fc1f434c5
--- /dev/null
+++ b/web/src/components/JurorsLeaderboardButton.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+
+import RankingIcon from "svgs/icons/ranking.svg";
+
+import { BlueIconTextButtonContainer } from "./BlueIconTextButtonContainer";
+import { InternalLink } from "./InternalLink";
+
+const JurorsLeaderboardButton: React.FC = () => {
+ return (
+
+
+
+ Jurors Leaderboard
+
+
+ );
+};
+
+export default JurorsLeaderboardButton;
diff --git a/web/src/components/Popup/MiniGuides/JurorLevels.tsx b/web/src/components/Popup/MiniGuides/JurorLevels.tsx
index 9e2b98c1d..b8043e26f 100644
--- a/web/src/components/Popup/MiniGuides/JurorLevels.tsx
+++ b/web/src/components/Popup/MiniGuides/JurorLevels.tsx
@@ -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";
@@ -35,16 +35,16 @@ const leftPageContents = [
title: "Juror Level 1: Pythagoras",
paragraphs: [
"Jurors are classified into distinct levels according to their performance starting from Level 1.",
- "Level 1: Jurors with 0 cases arbitrated, OR Jurors with ≥ 1 case arbitrated with 0-70% of coherent votes.",
+ "Level 1: Jurors with ≥ 1 case arbitrated with 0-70% of coherent votes.",
],
},
{
title: "Juror Level 2: Socrates",
- paragraphs: ["Level 2: Jurors with ≥ 3 cases arbitrated with 70%-80% of coherent votes."],
+ paragraphs: ["Level 2: Jurors with ≥ 3 cases arbitrated with more than 70% coherent votes."],
},
{
title: "Juror Level 3: Plato",
- paragraphs: ["Level 3: Jurors with ≥ 7 cases arbitrated with 80%-90% of coherent votes."],
+ paragraphs: ["Level 3: Jurors with ≥ 7 cases arbitrated with more than 80% of coherent votes."],
},
{
title: "Juror Level 4: Aristotle",
diff --git a/web/src/hooks/queries/useJurorsByCoherenceScore.ts b/web/src/hooks/queries/useJurorsByCoherenceScore.ts
new file mode 100644
index 000000000..9bbce4f86
--- /dev/null
+++ b/web/src/hooks/queries/useJurorsByCoherenceScore.ts
@@ -0,0 +1,49 @@
+import { useQuery } from "@tanstack/react-query";
+import { useGraphqlBatcher } from "context/GraphqlBatcher";
+import { graphql } from "src/graphql";
+import { JurorsByCoherenceScoreQuery } from "src/graphql/graphql";
+
+const jurorsByCoherenceScoreQuery = graphql(`
+ query JurorsByCoherenceScore(
+ $skip: Int
+ $first: Int
+ $orderBy: User_orderBy
+ $orderDirection: OrderDirection
+ $search: String
+ ) {
+ users(
+ first: $first
+ skip: $skip
+ orderBy: $orderBy
+ orderDirection: $orderDirection
+ where: { totalResolvedVotes_gt: 0, userAddress_contains: $search }
+ ) {
+ id
+ coherenceScore
+ totalCoherentVotes
+ totalResolvedVotes
+ totalResolvedDisputes
+ }
+ }
+`);
+
+export const useJurorsByCoherenceScore = (
+ skip = 0,
+ first = 20,
+ orderBy: string,
+ orderDirection: string,
+ search = ""
+) => {
+ const { graphqlBatcher } = useGraphqlBatcher();
+
+ return useQuery({
+ queryKey: ["JurorsByCoherenceScore", skip, first, orderBy, orderDirection, search],
+ staleTime: Infinity,
+ queryFn: async () =>
+ await graphqlBatcher.fetch({
+ id: crypto.randomUUID(),
+ document: jurorsByCoherenceScoreQuery,
+ variables: { skip, first, orderBy, orderDirection, search: search.toLowerCase() },
+ }),
+ });
+};
diff --git a/web/src/hooks/queries/useTopUsersByCoherenceScore.ts b/web/src/hooks/queries/useTopUsersByCoherenceScore.ts
deleted file mode 100644
index add534914..000000000
--- a/web/src/hooks/queries/useTopUsersByCoherenceScore.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { useQuery } from "@tanstack/react-query";
-
-import { useGraphqlBatcher } from "context/GraphqlBatcher";
-import { isUndefined } from "utils/index";
-
-import { graphql } from "src/graphql";
-import { TopUsersByCoherenceScoreQuery } from "src/graphql/graphql";
-export type { TopUsersByCoherenceScoreQuery };
-
-const topUsersByCoherenceScoreQuery = graphql(`
- query TopUsersByCoherenceScore($first: Int!, $orderBy: User_orderBy, $orderDirection: OrderDirection) {
- users(first: $first, orderBy: $orderBy, orderDirection: $orderDirection) {
- id
- coherenceScore
- totalCoherentVotes
- totalResolvedVotes
- totalResolvedDisputes
- }
- }
-`);
-
-export const useTopUsersByCoherenceScore = (first = 5) => {
- const isEnabled = !isUndefined(first);
- const { graphqlBatcher } = useGraphqlBatcher();
-
- return useQuery({
- queryKey: [`TopUsersByCoherenceScore${first}`],
- enabled: isEnabled,
- staleTime: Infinity,
- queryFn: async () =>
- isEnabled
- ? await graphqlBatcher.fetch({
- id: crypto.randomUUID(),
- document: topUsersByCoherenceScoreQuery,
- variables: {
- first: first,
- orderBy: "coherenceScore",
- orderDirection: "desc",
- },
- })
- : undefined,
- });
-};
diff --git a/web/src/hooks/queries/useTotalLeaderboardJurors.ts b/web/src/hooks/queries/useTotalLeaderboardJurors.ts
new file mode 100644
index 000000000..ff2cd8ea9
--- /dev/null
+++ b/web/src/hooks/queries/useTotalLeaderboardJurors.ts
@@ -0,0 +1,32 @@
+import { useQuery } from "@tanstack/react-query";
+
+import { useGraphqlBatcher } from "context/GraphqlBatcher";
+
+import { graphql } from "src/graphql";
+import { TotalLeaderboardJurorsQuery } from "src/graphql/graphql";
+export type { TotalLeaderboardJurorsQuery };
+
+const totalLeaderboardJurorsQuery = graphql(`
+ query TotalLeaderboardJurors($id: ID!) {
+ counter(id: $id) {
+ totalLeaderboardJurors
+ }
+ }
+`);
+
+export const useTotalLeaderboardJurors = () => {
+ const { graphqlBatcher } = useGraphqlBatcher();
+
+ return useQuery({
+ queryKey: [`TotalLeaderboardJurors`],
+ staleTime: Infinity,
+ queryFn: async () =>
+ await graphqlBatcher.fetch({
+ id: crypto.randomUUID(),
+ document: totalLeaderboardJurorsQuery,
+ variables: {
+ id: 0,
+ },
+ }),
+ });
+};
diff --git a/web/src/layout/Header/navbar/Explore.tsx b/web/src/layout/Header/navbar/Explore.tsx
index b28482eee..8c4960d7a 100644
--- a/web/src/layout/Header/navbar/Explore.tsx
+++ b/web/src/layout/Header/navbar/Explore.tsx
@@ -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/1/desc/all", text: "Jurors" },
{ to: "/get-pnk", text: "Get PNK" },
];
diff --git a/web/src/layout/Header/navbar/Menu/Settings/General/WalletAndProfile.tsx b/web/src/layout/Header/navbar/Menu/Settings/General/WalletAndProfile.tsx
new file mode 100644
index 000000000..57931035c
--- /dev/null
+++ b/web/src/layout/Header/navbar/Menu/Settings/General/WalletAndProfile.tsx
@@ -0,0 +1,61 @@
+import React from "react";
+import styled from "styled-components";
+
+import { hoverLongTransitionTiming } from "styles/commonStyles";
+
+import ArrowIcon from "svgs/icons/arrow.svg";
+
+import { AddressOrName, IdenticonOrAvatar } from "components/ConnectWallet/AccountDisplay";
+import { StyledArrowLink } from "components/StyledArrowLink";
+import { ISettings } from "../../../index";
+
+const Container = styled.div`
+ ${hoverLongTransitionTiming}
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 16px 32px;
+ gap: 24px;
+ border: 1px solid ${({ theme }) => theme.stroke};
+ border-radius: 30px;
+
+ > label {
+ color: ${({ theme }) => theme.primaryText};
+ font-size: 16px;
+ font-weight: 600;
+ }
+
+ :hover {
+ background-color: ${({ theme }) => theme.lightBlue};
+ }
+`;
+
+const AvatarAndAddressContainer = styled.div`
+ display: flex;
+ flex-direction: row;
+ gap: 8px;
+`;
+
+const ReStyledArrowLink = styled(StyledArrowLink)`
+ font-size: 14px;
+
+ > svg {
+ height: 14px;
+ width: 14px;
+ }
+`;
+
+const WalletAndProfile: React.FC = ({ toggleIsSettingsOpen }) => {
+ return (
+
+
+
+
+
+
+ My Profile
+
+
+ );
+};
+export default WalletAndProfile;
diff --git a/web/src/layout/Header/navbar/Menu/Settings/General.tsx b/web/src/layout/Header/navbar/Menu/Settings/General/index.tsx
similarity index 54%
rename from web/src/layout/Header/navbar/Menu/Settings/General.tsx
rename to web/src/layout/Header/navbar/Menu/Settings/General/index.tsx
index 398f6673d..b15dc8b1b 100644
--- a/web/src/layout/Header/navbar/Menu/Settings/General.tsx
+++ b/web/src/layout/Header/navbar/Menu/Settings/General/index.tsx
@@ -1,23 +1,23 @@
-import React, { useMemo } from "react";
+import React from "react";
import styled from "styled-components";
import { useAccount, useDisconnect } from "wagmi";
import { Button } from "@kleros/ui-components-library";
-import { AddressOrName, ChainDisplay, IdenticonOrAvatar } from "components/ConnectWallet/AccountDisplay";
+import { ChainDisplay } from "components/ConnectWallet/AccountDisplay";
import { EnsureChain } from "components/EnsureChain";
+import WalletAndProfile from "./WalletAndProfile";
+import { ISettings } from "../../../index";
const Container = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
- margin-top: 12px;
`;
const StyledChainContainer = styled.div`
display: flex;
- height: 34px;
gap: 0.5rem;
justify-content: center;
align-items: center;
@@ -33,50 +33,23 @@ const StyledChainContainer = styled.div`
}
`;
-const StyledAddressContainer = styled.div`
- display: flex;
- justify-content: center;
- > label {
- color: ${({ theme }) => theme.primaryText};
- font-size: 16px;
- font-weight: 600;
- }
-`;
-
-const StyledAvatarContainer = styled.div`
- display: flex;
- justify-content: center;
- margin-top: 12px;
-`;
-
const StyledButton = styled.div`
display: flex;
justify-content: center;
- margin-top: 16px;
+ margin-top: 8px;
`;
const EnsureChainContainer = styled.div`
display: flex;
justify-content: center;
- padding: 16px;
+ padding-top: 24px;
+ padding-bottom: 20px;
`;
const UserContainer = styled.div`
display: flex;
flex-direction: column;
- gap: 12px;
-`;
-
-const StyledA = styled.a`
- text-decoration: none;
- label {
- cursor: pointer;
- color: ${({ theme }) => theme.primaryBlue};
- }
-
- :hover {
- text-decoration: underline;
- }
+ gap: 16px;
`;
export const DisconnectWalletButton: React.FC = () => {
@@ -84,12 +57,8 @@ export const DisconnectWalletButton: React.FC = () => {
return