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