/ src / modules / governance / proposal / VotersListContainer.tsx
VotersListContainer.tsx
  1  import { Trans } from '@lingui/macro';
  2  import { Box, Button, CircularProgress, Typography, useMediaQuery, useTheme } from '@mui/material';
  3  import { useState } from 'react';
  4  import { Row } from 'src/components/primitives/Row';
  5  import { ProposalVotes } from 'src/hooks/governance/useProposalVotes';
  6  import { useRootStore } from 'src/store/root';
  7  import { AIP } from 'src/utils/mixPanelEvents';
  8  
  9  import { ProposalVoteInfo } from '../utils/formatProposal';
 10  import { VotersList } from './VotersList';
 11  import { VotersListModal } from './VotersListModal';
 12  
 13  type VotersListProps = {
 14    proposal: ProposalVoteInfo;
 15    proposalVotes: ProposalVotes;
 16  };
 17  
 18  export type GovernanceVoter = {
 19    address: string;
 20    ensName: string | null;
 21    votingPower: number;
 22    twitterAvatar: string | null;
 23    support: boolean;
 24  };
 25  
 26  export type VotersData = {
 27    yaes: GovernanceVoter[];
 28    nays: GovernanceVoter[];
 29    combined: GovernanceVoter[];
 30  };
 31  
 32  export const VotersListContainer = ({ proposal, proposalVotes }: VotersListProps): JSX.Element => {
 33    const [votersModalOpen, setVotersModalOpen] = useState(false);
 34    const { breakpoints } = useTheme();
 35    const mdScreen = useMediaQuery(breakpoints.only('md'));
 36    const trackEvent = useRootStore((store) => store.trackEvent);
 37  
 38    const handleOpenAllVotes = () => {
 39      trackEvent(AIP.VIEW_ALL_VOTES);
 40      setVotersModalOpen(true);
 41    };
 42  
 43    if (false)
 44      return (
 45        <Box sx={{ mt: 8, mb: 12 }}>
 46          <Row sx={{ mb: 3 }}>
 47            <Typography sx={{ ml: 'auto' }} variant="subheader2" color="text.secondary">
 48              <Trans>Votes</Trans>
 49            </Typography>
 50          </Row>
 51          <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
 52            <CircularProgress size={24} sx={{ my: 4 }} />
 53          </Box>
 54        </Box>
 55      );
 56  
 57    if (false)
 58      return (
 59        <Box sx={{ mt: 8, mb: 12 }}>
 60          <Row sx={{ mb: 3 }}>
 61            <Typography sx={{ ml: 'auto' }} variant="subheader2" color="text.secondary">
 62              <Trans>Votes</Trans>
 63            </Typography>
 64          </Row>
 65          <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', mt: 8 }}>
 66            <Typography variant="helperText" color="error.main">
 67              <Trans>Failed to load proposal voters. Please refresh the page.</Trans>
 68            </Typography>
 69          </Box>
 70        </Box>
 71      );
 72  
 73    if (!proposalVotes || proposalVotes.combinedVotes.length === 0) return <Box sx={{ mt: 8 }} />;
 74  
 75    return (
 76      <Box sx={{ my: 8 }}>
 77        <Row sx={{ mb: 3 }}>
 78          <Typography variant="subheader2" color="text.secondary">
 79            {proposalVotes.combinedVotes.length > 10 ? (
 80              <Trans>Top 10 addresses</Trans>
 81            ) : (
 82              <Trans>Addresses</Trans>
 83            )}
 84          </Typography>
 85          <Typography variant="subheader2" color="text.secondary">
 86            <Trans>Votes</Trans>
 87          </Typography>
 88        </Row>
 89        <VotersList
 90          compact={mdScreen}
 91          voters={proposalVotes.combinedVotes.slice(0, 10)}
 92          sx={{ my: 4, pr: 2.25 }}
 93        />
 94        {proposalVotes.combinedVotes.length > 10 && (
 95          <Button variant="outlined" fullWidth onClick={handleOpenAllVotes}>
 96            <Trans>View all votes</Trans>
 97          </Button>
 98        )}
 99        {votersModalOpen && (
100          <VotersListModal
101            open={votersModalOpen}
102            close={() => setVotersModalOpen(false)}
103            proposal={proposal}
104            voters={proposalVotes}
105          />
106        )}
107      </Box>
108    );
109  };