Skip to content

Commit 9401c9b

Browse files
authored
Merge pull request #2098 from kleros/feat/add-available-and-staked-amounts-to-profile
feat: add available stake, effectivestake
2 parents 9895c7c + da90234 commit 9401c9b

File tree

8 files changed

+156
-89
lines changed

8 files changed

+156
-89
lines changed

web/src/components/NumberDisplay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const NumberDisplay: React.FC<INumberDisplay> = ({
3535
}) => {
3636
const parsedValue = Number(value);
3737
const formattedValue = commify(getFormattedValue(parsedValue, decimals));
38-
const tooltipValue = isCurrency ? `${unit} ${value}` : `${value} ${unit}`;
38+
const tooltipValue = isCurrency ? `${unit} ${commify(value)}` : `${commify(value)} ${unit}`;
3939
const displayUnit = showUnitInDisplay ? unit : "";
4040
const displayValue = isCurrency ? `${displayUnit} ${formattedValue}` : `${formattedValue} ${displayUnit}`;
4141

web/src/pages/Profile/Courts/Header.tsx

Lines changed: 0 additions & 79 deletions
This file was deleted.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import React from "react";
2+
import styled, { css } from "styled-components";
3+
4+
import { useSearchParams } from "react-router-dom";
5+
import { formatUnits } from "viem";
6+
7+
import LockerIcon from "svgs/icons/locker.svg";
8+
import PnkIcon from "svgs/icons/pnk.svg";
9+
10+
import { isUndefined } from "utils/index";
11+
12+
import { landscapeStyle } from "styles/landscapeStyle";
13+
import { responsiveSize } from "styles/responsiveSize";
14+
15+
import NumberDisplay from "components/NumberDisplay";
16+
17+
const Container = styled.div`
18+
display: flex;
19+
flex-direction: row;
20+
flex-wrap: wrap;
21+
width: 100%;
22+
gap: 4px 16px;
23+
align-items: center;
24+
margin-bottom: ${responsiveSize(16, 24)};
25+
26+
${landscapeStyle(
27+
() => css`
28+
justify-content: space-between;
29+
`
30+
)}
31+
`;
32+
33+
const LockedPnk = styled.div`
34+
display: flex;
35+
flex-wrap: nowrap;
36+
gap: 8px;
37+
align-items: center;
38+
justify-content: center;
39+
`;
40+
41+
const StakesGroup = styled.div`
42+
display: flex;
43+
gap: 12px 24px;
44+
align-items: center;
45+
flex-wrap: wrap;
46+
`;
47+
48+
const AvailablePnk = styled.div`
49+
display: flex;
50+
flex-wrap: nowrap;
51+
gap: 8px;
52+
align-items: center;
53+
justify-content: center;
54+
`;
55+
56+
const EffectivePnk = styled.div`
57+
display: flex;
58+
flex-wrap: nowrap;
59+
gap: 8px;
60+
align-items: center;
61+
justify-content: center;
62+
`;
63+
64+
const StyledTitle = styled.h1`
65+
margin-bottom: 0;
66+
font-size: ${responsiveSize(20, 24)};
67+
`;
68+
69+
const StyledLockerIcon = styled(LockerIcon)`
70+
fill: ${({ theme }) => theme.secondaryPurple};
71+
width: 14px;
72+
height: 14px;
73+
margin-bottom: 1px;
74+
`;
75+
76+
const StyledPnkIcon = styled(PnkIcon)`
77+
fill: ${({ theme }) => theme.secondaryPurple};
78+
width: 14px;
79+
height: 14px;
80+
margin-bottom: 1px;
81+
`;
82+
83+
const StyledEffectivePnkIcon = styled(PnkIcon)`
84+
fill: ${({ theme }) => theme.secondaryPurple};
85+
width: 14px;
86+
height: 14px;
87+
margin-bottom: 1px;
88+
`;
89+
90+
interface IHeader {
91+
availableStake?: bigint;
92+
lockedStake?: bigint;
93+
effectiveStake?: bigint;
94+
}
95+
96+
const Header: React.FC<IHeader> = ({ availableStake, lockedStake, effectiveStake }) => {
97+
const formattedAvailableStake = !isUndefined(availableStake) && formatUnits(availableStake, 18);
98+
const formattedLockedStake = !isUndefined(lockedStake) && formatUnits(lockedStake, 18);
99+
const formattedEffectiveStake = !isUndefined(effectiveStake) && formatUnits(effectiveStake, 18);
100+
const [searchParams] = useSearchParams();
101+
const searchParamAddress = searchParams.get("address")?.toLowerCase();
102+
103+
return (
104+
<Container>
105+
<StyledTitle>{searchParamAddress ? "Their" : "My"} Stakes</StyledTitle>
106+
<StakesGroup>
107+
{!isUndefined(availableStake) ? (
108+
<AvailablePnk>
109+
<StyledPnkIcon />
110+
<label> Available: </label>
111+
<small>
112+
<NumberDisplay value={formattedAvailableStake.toString()} unit="PNK" />
113+
</small>
114+
</AvailablePnk>
115+
) : null}
116+
{!isUndefined(effectiveStake) ? (
117+
<EffectivePnk>
118+
<StyledEffectivePnkIcon />
119+
<label> Staked: </label>
120+
<small>
121+
<NumberDisplay value={formattedEffectiveStake.toString()} unit="PNK" />
122+
</small>
123+
</EffectivePnk>
124+
) : null}
125+
{!isUndefined(lockedStake) ? (
126+
<LockedPnk>
127+
<StyledLockerIcon />
128+
<label> Locked: </label>
129+
<small>
130+
<NumberDisplay value={formattedLockedStake.toString()} unit="PNK" />
131+
</small>
132+
</LockedPnk>
133+
) : null}
134+
</StakesGroup>
135+
</Container>
136+
);
137+
};
138+
139+
export default Header;

web/src/pages/Profile/Courts/index.tsx renamed to web/src/pages/Profile/Stakes/index.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ const StyledLabel = styled.label`
3535
font-size: ${responsiveSize(14, 16)};
3636
`;
3737

38-
interface ICourts {
38+
interface IStakes {
3939
addressToQuery: `0x${string}`;
4040
}
4141

42-
const Courts: React.FC<ICourts> = ({ addressToQuery }) => {
42+
const Stakes: React.FC<IStakes> = ({ addressToQuery }) => {
4343
const { data: stakeData, isLoading } = useJurorStakeDetailsQuery(addressToQuery);
4444
const { data: jurorBalance } = useReadSortitionModuleGetJurorBalance({
4545
args: [addressToQuery, BigInt(1)],
@@ -48,11 +48,15 @@ const Courts: React.FC<ICourts> = ({ addressToQuery }) => {
4848
const searchParamAddress = searchParams.get("address")?.toLowerCase();
4949
const stakedCourts = stakeData?.jurorTokensPerCourts?.filter(({ staked }) => staked > 0);
5050
const isStaked = stakedCourts && stakedCourts.length > 0;
51+
const availableStake = jurorBalance?.[0];
5152
const lockedStake = jurorBalance?.[1];
53+
const effectiveStake = stakeData?.jurorTokensPerCourts?.[0]?.effectiveStake
54+
? BigInt(stakeData.jurorTokensPerCourts[0].effectiveStake)
55+
: undefined;
5256

5357
return (
5458
<Container>
55-
<Header lockedStake={lockedStake ?? BigInt(0)} />
59+
<Header {...{ lockedStake, availableStake, effectiveStake }} />
5660
{isLoading ? <Skeleton /> : null}
5761
{!isStaked && !isLoading ? (
5862
<StyledLabel>{searchParamAddress ? "They" : "You"} are not staked in any court</StyledLabel>
@@ -70,4 +74,4 @@ const Courts: React.FC<ICourts> = ({ addressToQuery }) => {
7074
);
7175
};
7276

73-
export default Courts;
77+
export default Stakes;

web/src/pages/Profile/index.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
import React, { useMemo } from "react";
2-
32
import styled, { css } from "styled-components";
4-
import { MAX_WIDTH_LANDSCAPE, landscapeStyle } from "styles/landscapeStyle";
5-
import { responsiveSize } from "styles/responsiveSize";
63

74
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
85
import { useAccount } from "wagmi";
96

107
import { isUndefined } from "utils/index";
118
import { decodeURIFilter, useRootPath } from "utils/uri";
9+
1210
import { DisputeDetailsFragment, useMyCasesQuery } from "queries/useCasesQuery";
1311
import { useUserQuery } from "queries/useUser";
12+
1413
import { Dispute_Filter, OrderDirection, UserDetailsFragment } from "src/graphql/graphql";
1514

15+
import { MAX_WIDTH_LANDSCAPE, landscapeStyle } from "styles/landscapeStyle";
16+
import { responsiveSize } from "styles/responsiveSize";
17+
1618
import CasesDisplay from "components/CasesDisplay";
1719
import ConnectWallet from "components/ConnectWallet";
1820
import FavoriteCases from "components/FavoriteCases";
1921
import ScrollTop from "components/ScrollTop";
20-
import Courts from "./Courts";
22+
2123
import JurorInfo from "./JurorInfo";
24+
import Stakes from "./Stakes";
2225

2326
const Container = styled.div`
2427
width: 100%;
@@ -110,7 +113,7 @@ const Profile: React.FC = () => {
110113
{isConnected || searchParamAddress ? (
111114
<>
112115
<JurorInfo {...{ addressToQuery }} />
113-
<Courts {...{ addressToQuery }} />
116+
<Stakes {...{ addressToQuery }} />
114117
<StyledCasesDisplay
115118
title={`${searchParamAddress ? "Their" : "My"} Cases`}
116119
disputes={userData?.user !== null ? (disputesData?.user?.disputes as DisputeDetailsFragment[]) : []}

0 commit comments

Comments
 (0)