From 5fcd49e5cd6cc73e31261e7b3243f1a631e2df3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sza=C5=82owski?= Date: Fri, 31 Jan 2025 11:45:04 +0100 Subject: [PATCH] feat: display not voted in drep submitted votes --- govtool/backend/sql/list-proposals.sql | 2 +- .../src/components/atoms/VotePill.tsx | 58 +++++++++++++------ .../components/molecules/VotesSubmitted.tsx | 56 +++++++++++++----- govtool/frontend/src/i18n/locales/en.json | 3 +- govtool/frontend/src/types/global.d.ts | 2 +- 5 files changed, 86 insertions(+), 35 deletions(-) diff --git a/govtool/backend/sql/list-proposals.sql b/govtool/backend/sql/list-proposals.sql index 2643d8bd2..ad66a5c7e 100644 --- a/govtool/backend/sql/list-proposals.sql +++ b/govtool/backend/sql/list-proposals.sql @@ -21,7 +21,7 @@ DRepVotingPower AS ( SUM(CASE WHEN drep_hash.view = 'drep_always_abstain' THEN amount ELSE 0 END) AS abstain FROM drep_hash - LEFT JOIN drep_distr ON drep_hash.id = drep_distr.hash_id + LEFT JOIN drep_distr ON drep_hash.id = drep_distr.hash_id AND drep_distr.epoch_no = (SELECT MAX(no) FROM epoch) WHERE drep_hash.view IN ('drep_always_no_confidence', 'drep_always_abstain') ), CommitteeData AS ( diff --git a/govtool/frontend/src/components/atoms/VotePill.tsx b/govtool/frontend/src/components/atoms/VotePill.tsx index cd37c9e02..8833024d1 100644 --- a/govtool/frontend/src/components/atoms/VotePill.tsx +++ b/govtool/frontend/src/components/atoms/VotePill.tsx @@ -3,30 +3,60 @@ import { Box, Typography } from "@mui/material"; import { Vote } from "@models"; +const borderColorMap = { + yes: "#C0E4BA", + no: "#EDACAC", + abstain: "#99ADDE", + notVoted: "#EAE9F0", +}; + +const bgColorMap = { + yes: "#F0F9EE", + no: "#FBEBEB", + abstain: "#E6EBF7", + notVoted: "#F5F5F8", +}; + +const voteLabelKey = { + yes: "votes.yes", + no: "votes.no", + abstain: "votes.abstain", + notVoted: "votes.notVoted", +}; + +const ccVoteLabelKey = { + yes: "votes.constitutional", + no: "votes.unconstitutional", + abstain: "votes.abstain", + notVoted: "", +}; + +type VoteExtended = Vote | "notVoted"; + export const VotePill = ({ vote, width, maxWidth, isCC, }: { - vote: Vote; + vote: VoteExtended; width?: number; maxWidth?: number; isCC?: boolean; }) => { const { t } = useTranslation(); - const VOTE = vote.toLowerCase() as "yes" | "no" | "abstain"; + + const bgColor = bgColorMap[vote]; + const borderColor = borderColorMap[vote]; + const labelKey = isCC ? ccVoteLabelKey[vote] : voteLabelKey[vote]; + return ( - {t( - `votes.${ - isCC - ? VOTE === "yes" - ? "constitutional" - : vote === "no" - ? "unconstitutional" - : VOTE - : VOTE - }`, - )} + {t(labelKey)} ); diff --git a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx index b743de7b3..bc81e4e7c 100644 --- a/govtool/frontend/src/components/molecules/VotesSubmitted.tsx +++ b/govtool/frontend/src/components/molecules/VotesSubmitted.tsx @@ -4,7 +4,10 @@ import { Box } from "@mui/material"; import { IMAGES, SECURITY_RELEVANT_PARAMS_MAP } from "@consts"; import { Typography, VotePill } from "@atoms"; import { useTranslation } from "@hooks"; -import { correctVoteAdaFormat, getGovActionVotingThresholdKey } from "@utils"; +import { + correctDRepDirectoryFormat, + getGovActionVotingThresholdKey, +} from "@utils"; import { SubmittedVotesData } from "@models"; import { useFeatureFlag, useAppContext } from "@/context"; @@ -42,17 +45,28 @@ export const VotesSubmitted = ({ areCCVoteTotalsDisplayed, } = useFeatureFlag(); const { t } = useTranslation(); - const { epochParams } = useAppContext(); + const { epochParams, networkMetrics } = useAppContext(); - const dRepYesVotesPercentage = - dRepYesVotes + dRepNoVotes - ? (dRepYesVotes / (dRepYesVotes + dRepNoVotes)) * 100 - : undefined; - const dRepNoVotesPercentage = dRepYesVotesPercentage - ? 100 - dRepYesVotesPercentage - : dRepNoVotes - ? 100 + const totalStakeControlledByDReps = + networkMetrics?.totalStakeControlledByDReps ?? 0; + + const totalDRepVotes = totalStakeControlledByDReps + ? totalStakeControlledByDReps - dRepAbstainVotes + : undefined; + const dRepYesVotesPercentage = totalDRepVotes + ? (dRepYesVotes / totalDRepVotes) * 100 : undefined; + const dRepNoVotesPercentage = totalDRepVotes + ? (dRepNoVotes / totalDRepVotes) * 100 + : undefined; + const dRepNotVotedVotes = totalStakeControlledByDReps + ? totalStakeControlledByDReps - + dRepYesVotes - + dRepNoVotes - + dRepAbstainVotes + : undefined; + const dRepNotVotedVotesPercentage = + 100 - (dRepYesVotesPercentage ?? 0) - (dRepNoVotesPercentage ?? 0); const poolYesVotesPercentage = poolYesVotes + poolNoVotes @@ -123,6 +137,8 @@ export const VotesSubmitted = ({ noVotes={dRepNoVotes} noVotesPercentage={dRepNoVotesPercentage} abstainVotes={dRepAbstainVotes} + notVotedVotes={dRepNotVotedVotes} + notVotedPercentage={dRepNotVotedVotesPercentage} threshold={(() => { const votingThresholdKey = getGovActionVotingThresholdKey({ govActionType: type, @@ -174,6 +190,8 @@ type VotesGroupProps = { yesVotesPercentage?: number; noVotes: number; noVotesPercentage?: number; + notVotedVotes?: number; + notVotedPercentage?: number; abstainVotes: number; threshold?: number | null; }; @@ -184,6 +202,8 @@ const VotesGroup = ({ yesVotesPercentage, noVotes, noVotesPercentage, + notVotedVotes, + notVotedPercentage, abstainVotes, threshold, }: VotesGroupProps) => { @@ -219,7 +239,15 @@ const VotesGroup = ({ percentage={noVotesPercentage} value={noVotes} /> - {threshold !== undefined && ( + {typeof notVotedVotes === "number" && ( + + )} + {threshold !== undefined && threshold !== null && ( - {threshold} + {threshold * 100}% )} @@ -285,7 +313,9 @@ const Vote = ({ type, vote, value, percentage }: VoteProps) => ( fontWeight: "500", }} > - {type !== "ccCommittee" ? `₳ ${correctVoteAdaFormat(value)}` : value} + {type !== "ccCommittee" + ? `₳ ${correctDRepDirectoryFormat(value)}` + : value} {vote !== "abstain" && typeof percentage === "number" && (