import { Box, Grid, LinearProgress, styled } from "@mui/material";
import { formatValue } from "../../lib/utils";
import { successGreen } from "../../consts/colors";
import { Typography } from "../Atoms/Typography";
import { VoteSectionLoader } from "../Loaders/VoteSectionLoader";
import { theme } from "../../theme";
import { useTranslation } from "../../contexts/I18nContext";
import VoteMetricsTable from "./VoteMetricsTable";
const {
palette: { badgeColors, midRed },
} = theme;
export type VoteMetric = {
label: string;
value: number | string;
testId?: string;
isHighlighted?: boolean;
isIndented?: boolean;
indentDepth?: number;
};
type VoteSectionProps = {
title: string;
yesVotes?: number;
noVotes?: number;
noTotalVotes?: number;
noConfidenceVotes?: number;
totalControlled?: number;
totalAbstainVotes?: number;
autoAbstainVotes?: number;
explicitAbstainVotes?: number;
notVotedVotes?: number;
threshold?: number | null;
thresholdBarValue?: number;
ratificationThreshold?: number;
yesPercentage?: number;
noPercentage?: number;
isCC?: boolean;
isDisplayed: boolean;
isLoading?: boolean;
isDataReady?: boolean;
dataTestId?: string;
defaultExpanded?: boolean;
};
const ProgressWrapper = styled(Box)({
position: "relative",
width: "100%",
});
const ProgressContainer = styled(Box)({
position: "relative",
width: "100%",
height: 32,
borderRadius: 20,
overflow: "hidden",
});
const StyledLinearProgress = styled(LinearProgress)({
height: "100%",
borderRadius: 10,
backgroundColor: midRed,
".MuiLinearProgress-bar": {
backgroundColor: successGreen.c500,
},
});
const PercentageOverlay = styled(Box)({
position: "absolute",
top: 0,
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
pointerEvents: "none",
});
const PercentageText = styled(Typography)({
fontSize: 13,
fontWeight: 600,
color: "textBlack",
padding: "0 10px",
zIndex: 10,
whiteSpace: "nowrap",
[theme.breakpoints.down("sm")]: {
padding: "0 4px",
},
});
const ThresholdLine = styled(Box)({
position: "absolute",
width: "2px",
height: "100%",
backgroundColor: badgeColors.darkPurple,
zIndex: 4,
});
const ThresholdIndicator = styled(Box)<{ left: number }>(({ left }) => ({
position: "absolute",
left: `${left}%`,
top: "-24px",
transform: "translateX(-50%)",
display: "flex",
flexDirection: "column",
alignItems: "center",
zIndex: 5,
}));
const ThresholdBubble = styled(Box)({
backgroundColor: badgeColors.darkPurple,
borderRadius: "12px",
padding: "2px 8px",
border: `1px solid ${badgeColors.darkPurple}`,
boxShadow: "0px 1px 2px rgba(0,0,0,0.08)",
});
const ThresholdText = styled(Typography)({
fontSize: 12,
fontWeight: 600,
color: "white",
lineHeight: 1.2,
textWrap: 'nowrap'
});
const ThresholdArrow = styled(Box)({
width: 0,
height: 0,
borderLeft: "6px solid transparent",
borderRight: "6px solid transparent",
borderTop: `6px solid ${badgeColors.darkPurple}`,
marginTop: "-1px",
});
export const VoteSection = ({
title,
yesVotes = 0,
noVotes = 0,
noTotalVotes = 0,
totalControlled = 0,
totalAbstainVotes = 0,
autoAbstainVotes = 0,
explicitAbstainVotes = 0,
noConfidenceVotes = 0,
notVotedVotes = 0,
threshold = null,
yesPercentage = 0,
noPercentage = 0,
ratificationThreshold = 0,
isCC = false,
isDisplayed,
isLoading = true,
isDataReady = false,
dataTestId,
defaultExpanded = false,
}: VoteSectionProps) => {
const { t } = useTranslation();
const collapsedMetrics: VoteMetric[] = [
{
label: isCC
? t("outcome.votes.numberOfCCs")
: t("outcome.votes.totalActiveStake"),
value: totalControlled,
testId: `${title}-total-controlled-amount`,
},
{
label: isCC
? t("outcome.votes.abstainVotes")
: t("outcome.votes.totalAbstain"),
value: totalAbstainVotes,
testId: `${title}-abstain-votes`,
},
{
label: isCC
? t("outcome.votes.notVoted")
: t("outcome.votes.ratificationThreshold"),
value: isCC ? notVotedVotes : ratificationThreshold,
testId: `${title}-ratification-threshold`,
},
];
const expandedMetrics: VoteMetric[] = [
{
label: t("outcome.votes.totalActiveStake"),
value: totalControlled,
testId: `${title}-total-controlled-amount`,
},
{
label: t("outcome.votes.ratificationThreshold"),
value: ratificationThreshold,
testId: `${title}-ratification-threshold`,
isHighlighted: true,
isIndented: true,
indentDepth: 1,
},
{
label: t("outcome.votes.yes"),
value: yesVotes,
testId: `${title}-yes-votes`,
isIndented: true,
indentDepth: 2,
},
{
label: t("outcome.votes.no"),
value: noVotes,
testId: `${title}-no-votes`,
isIndented: true,
indentDepth: 2,
},
{
label: t("outcome.votes.noConfidence"),
value: noConfidenceVotes,
testId: `${title}-no-confidence-votes`,
isIndented: true,
indentDepth: 2,
},
{
label: t("outcome.votes.notVoted"),
value: notVotedVotes,
testId: `${title}-not-voted-votes`,
isIndented: true,
indentDepth: 2,
},
{
label: t("outcome.votes.totalAbstain"),
value: totalAbstainVotes,
testId: `${title}-abstain-votes`,
isHighlighted: true,
isIndented: true,
indentDepth: 1,
},
{
label: t("outcome.votes.autoAbstain"),
value: autoAbstainVotes,
testId: `${title}-abstain-votes`,
isIndented: true,
indentDepth: 2,
},
{
label: t("outcome.votes.explicit"),
value: explicitAbstainVotes,
testId: `${title}-abstain-votes`,
isIndented: true,
indentDepth: 2,
},
];
if (!isDataReady || isLoading) {
return ;
}
const thresholdValue = threshold
? isCC
? Number(Math.round((totalControlled - totalAbstainVotes) * threshold))
: threshold * ratificationThreshold
: 0;
const noVotesValue = isCC ? noVotes : noTotalVotes;
return (
{title}
{!isDisplayed && (
{t(title)}{" "}
{t("outcome.votes.votingNotAvailable")}{" "}
{t("outcome.votes.onThisTypeOfAction")}
)}
{isDisplayed && (
{threshold !== null && (
<>
{formatValue(thresholdValue, isCC)} -{" "}
{(threshold * 100).toFixed(0)}
%
>
)}
{t("outcome.votes.yes")}
{t("outcome.votes.no")}
{`${formatValue(yesVotes, isCC)} - ${yesPercentage?.toFixed(
2
)}%`}
{`${formatValue(noVotesValue, isCC)} - ${noPercentage?.toFixed(
2
)}%`}
)}
);
};