Skip to content

Commit

Permalink
Merge pull request #785 from alleslabs/feat/cfe-216-vote-details-quorum
Browse files Browse the repository at this point in the history
feat: quorum information on vote section
  • Loading branch information
songwongtp committed Feb 15, 2024
2 parents 867645f + 3865869 commit 302b75f
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- [#785](https://github.com/alleslabs/celatone-frontend/pull/785) Quorum status on vote details section
- [#782](https://github.com/alleslabs/celatone-frontend/pull/782) Show proposal details on vote details section tabs
- [#779](https://github.com/alleslabs/celatone-frontend/pull/779) Proposal period overview voting - no with veto alert
- [#778](https://github.com/alleslabs/celatone-frontend/pull/778) Proposal period overview voting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,20 @@ interface VoteQuorumCircleProps {
nonAbstainVotes: Big;
totalVotes: Big;
isCompact: boolean;
isBgGray?: boolean;
}

export const VoteQuorumCircle = ({
quorum,
nonAbstainVotes,
totalVotes,
isCompact,
isBgGray,
}: VoteQuorumCircleProps) => {
const nonAbstainVotesAngle = nonAbstainVotes.toNumber() * 360;

const totalVotesAngle = totalVotes.toNumber() * 360;
const totalVotesPercent = formatPrettyPercent(
totalVotes.toNumber(),
isCompact ? 1 : 2
);
const totalVotesPercent = formatPrettyPercent(totalVotes.toNumber(), 1);

const quorumAngle = quorum * 360;
const quorumPercent = formatPrettyPercent(quorum);
Expand Down Expand Up @@ -51,7 +50,7 @@ export const VoteQuorumCircle = ({
<Circle
size={isCompact ? "52px" : "134px"}
position="absolute"
bgColor="background.main"
bgColor={isBgGray ? "gray.900" : "background.main"}
>
{!isCompact && (
<Text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { Text } from "@chakra-ui/react";
import { ProposalStatus } from "lib/types";
import { formatPrettyPercent } from "lib/utils";

interface VotingOverviewQuorumTextProps {
interface VoteQuorumTextProps {
status: ProposalStatus;
quorum: number;
totalVotes: Big;
isCompact: boolean;
}

const Established = () => (
Expand All @@ -20,37 +21,39 @@ const Established = () => (
</span>
);

export const VotingOverviewQuorumText = ({
export const VoteQuorumText = ({
status,
quorum,
totalVotes,
}: VotingOverviewQuorumTextProps) => {
isCompact,
}: VoteQuorumTextProps) => {
const fontVariant = isCompact ? "body2" : "body1";
const quorumPercent = formatPrettyPercent(quorum);
const isPassingQuorum = totalVotes.gte(quorum);

if (status === ProposalStatus.VOTING_PERIOD)
return isPassingQuorum ? (
<Text variant="body2" color="text.main">
<Text variant={fontVariant} color="text.main">
The proposal has successfully met the voting{" "}
<span style={{ fontWeight: 700 }}>{quorumPercent}</span> quorum and will
be <Established /> after the voting period ends.
</Text>
) : (
<Text variant="body2" color="text.main">
<Text variant={fontVariant} color="text.main">
The proposal required{" "}
<span style={{ fontWeight: 700 }}>{quorumPercent}</span> vote quorum to
establish.
</Text>
);

return isPassingQuorum ? (
<Text variant="body2" color="text.main">
<Text variant={fontVariant} color="text.main">
The proposal has successfully met the voting{" "}
<span style={{ fontWeight: 700 }}>{quorumPercent}</span> quorum and{" "}
<Established />.
</Text>
) : (
<Text variant="body2" color="text.main">
<Text variant={fontVariant} color="text.main">
This proposal{" "}
<span
style={{
Expand Down
45 changes: 45 additions & 0 deletions src/lib/pages/proposal-details/components/VpPercentCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Flex, Text, type FlexProps, Heading } from "@chakra-ui/react";

import { d0Formatter, formatPrettyPercent } from "lib/utils";

interface VpPercentCardProps {
name: string;
ratio: Big;
power: Big;
color: FlexProps["bgColor"];
isCompact: boolean;
}

export const VpPercentCard = ({
name,
ratio,
power,
color,
isCompact,
}: VpPercentCardProps) => (
<Flex
direction={isCompact ? "row-reverse" : "column"}
justifyContent="flex-end"
gap={2}
w="full"
>
<Flex direction="column" gap={isCompact ? 1 : 2} align="start">
<Text variant="body2" color="text.main">
{name}
</Text>
<Flex direction={isCompact ? "row" : "column"} gap={isCompact ? 2 : 0}>
<Heading as="h6" variant="h6" fontWeight={600}>
{formatPrettyPercent(ratio.toNumber())}
</Heading>
<Text variant="body2" color="text.dark">
({d0Formatter(power, "0")})
</Text>
</Flex>
</Flex>
<Flex
bgColor={color}
borderRadius={10}
{...(isCompact ? { w: 1, h: "full" } : { w: "full", h: 1 })}
/>
</Flex>
);
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const VotingOverviewBody = ({
);

if (isLoading) return <Loading my={0} />;
if (!params || !votesInfo) return <ErrorFetchingProposalInfos isParamsOnly />;
if (!params || !votesInfo) return <ErrorFetchingProposalInfos />;

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Box, Divider, Flex, Text } from "@chakra-ui/react";

import { VoteQuorumBadge } from "../../VoteQuorumBadge";
import { VoteQuorumCircle } from "../../VoteQuorumCircle";
import { VoteQuorumText } from "../../VoteQuorumText";
import { CustomIcon } from "lib/components/icon";
import { Tooltip } from "lib/components/Tooltip";
import {
Expand All @@ -15,8 +16,6 @@ import type {
} from "lib/types";
import { dateFromNow, formatPrettyPercent, formatUTC } from "lib/utils";

import { VotingOverviewQuorumText } from "./VotingOverviewQuorumText";

interface VotingOverviewQuorumProps {
proposalData: ProposalData;
params: ProposalParams;
Expand Down Expand Up @@ -82,10 +81,11 @@ export const VotingOverviewQuorum = ({
</Box>
</Tooltip>
<Flex direction="column" gap={2}>
<VotingOverviewQuorumText
<VoteQuorumText
status={proposalData.status}
quorum={quorum}
totalVotes={totalVotes}
isCompact
/>
<div>
<Text variant="body3" color="text.dark">
Expand Down
18 changes: 13 additions & 5 deletions src/lib/pages/proposal-details/components/vote-details/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,26 @@ import {
} from "@chakra-ui/react";

import { useMobile } from "lib/app-provider";
import type { ProposalData } from "lib/types";
import type {
Option,
ProposalData,
ProposalParams,
ProposalVotesInfo,
} from "lib/types";

import { DepositPeriodSection } from "./deposit-period/DepositPeriodSection";
import { VoteDetailsAccordionItem } from "./VoteDetailsAccordionItem";
import { VoteDetailsTab } from "./VoteDetailsTab";
import { VotingPeriod } from "./voting-period";

interface VoteDetailsProps {
export interface VoteDetailsProps {
proposalData: ProposalData;
votesInfo: Option<ProposalVotesInfo>;
params: Option<ProposalParams>;
isLoading: boolean;
}

export const VoteDetails = ({ proposalData }: VoteDetailsProps) => {
export const VoteDetails = ({ proposalData, ...props }: VoteDetailsProps) => {
const isMobile = useMobile();

return isMobile ? (
Expand All @@ -29,7 +37,7 @@ export const VoteDetails = ({ proposalData }: VoteDetailsProps) => {
<DepositPeriodSection />
</VoteDetailsAccordionItem>
<VoteDetailsAccordionItem step={2} proposalData={proposalData}>
<VotingPeriod id={proposalData.id} />
<VotingPeriod proposalData={proposalData} {...props} />
</VoteDetailsAccordionItem>
</Accordion>
</Flex>
Expand All @@ -52,7 +60,7 @@ export const VoteDetails = ({ proposalData }: VoteDetailsProps) => {
<DepositPeriodSection />
</TabPanel>
<TabPanel>
<VotingPeriod id={proposalData.id} />
<VotingPeriod proposalData={proposalData} {...props} />
</TabPanel>
</TabPanels>
</Tabs>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { Divider, Flex, Heading, Spacer, Text } from "@chakra-ui/react";
import big from "big.js";

import type { VoteDetailsProps } from "..";
import { ErrorFetchingProposalInfos } from "../../ErrorFetchingProposalInfos";
import { VoteQuorumBadge } from "../../VoteQuorumBadge";
import { VoteQuorumCircle } from "../../VoteQuorumCircle";
import { VoteQuorumText } from "../../VoteQuorumText";
import { VpPercentCard } from "../../VpPercentCard";
import { useMobile } from "lib/app-provider";
import { Loading } from "lib/components/Loading";
import {
extractParams,
normalizeVotesInfo,
} from "lib/pages/proposal-details/utils";

export const VotingQuorum = ({
proposalData,
params,
votesInfo,
isLoading,
}: VoteDetailsProps) => {
const isMobile = useMobile();
if (isLoading) return <Loading my={0} />;
if (!params || !votesInfo) return <ErrorFetchingProposalInfos />;

const { quorum } = extractParams(params, proposalData.isExpedited);
const { abstain, nonAbstainVotes, totalVotes } =
normalizeVotesInfo(votesInfo);

const votes = votesInfo.yes.add(votesInfo.no).add(votesInfo.noWithVeto);
const allVotes = votes.add(votesInfo.abstain);

return (
<Flex direction="column" gap={4}>
<Flex gap={2} align="center">
{isMobile ? (
<>
<VoteQuorumBadge
status={proposalData.status}
quorum={quorum}
totalVotes={totalVotes}
isCompact
/>
<Text variant="body1" color="text.main">
Quorum
</Text>
</>
) : (
<>
<Heading as="h6" variant="h6" textColor="text.main">
Vote Participations
</Heading>
<VoteQuorumBadge
status={proposalData.status}
quorum={quorum}
totalVotes={totalVotes}
isCompact={false}
/>
<Spacer />
<Text variant="body3" textColor="text.dark">
* Voting power displayed in bracket
</Text>
</>
)}
</Flex>
{isMobile && <Divider borderColor="gray.700" />}
<Flex
direction={{ base: "column", md: "row" }}
gap={{ base: 3, md: 12 }}
align="center"
textAlign={{ base: "center", md: "start" }}
w="full"
>
<VoteQuorumCircle
quorum={quorum}
nonAbstainVotes={nonAbstainVotes}
totalVotes={totalVotes}
isCompact={false}
isBgGray={!isMobile}
/>
<Flex direction="column" gap={4} w="full">
<VoteQuorumText
status={proposalData.status}
quorum={quorum}
totalVotes={totalVotes}
isCompact={false}
/>
<Flex direction={isMobile ? "column" : "row"} gap={isMobile ? 3 : 8}>
<VpPercentCard
name="Voted"
ratio={nonAbstainVotes}
power={votes}
color="primary.main"
isCompact={isMobile}
/>
<VpPercentCard
name="Voted Abstain"
ratio={abstain}
power={votesInfo.abstain}
color="secondary.main"
isCompact={isMobile}
/>
<Divider
orientation="vertical"
h="auto"
color="gray.700"
display={{ base: "none", lg: "flex" }}
/>
<VpPercentCard
name="Did not vote"
ratio={big(1).minus(totalVotes)}
power={votesInfo.totalVotingPower.minus(allVotes)}
color="gray.800"
isCompact={isMobile}
/>
</Flex>
</Flex>
</Flex>
</Flex>
);
};
Loading

0 comments on commit 302b75f

Please sign in to comment.