/ src / modules / governance / ProposalsV3List.tsx
ProposalsV3List.tsx
  1  import { Box, Paper, Skeleton, Stack } from '@mui/material';
  2  import { useState } from 'react';
  3  import InfiniteScroll from 'react-infinite-scroller';
  4  import { NoSearchResults } from 'src/components/NoSearchResults';
  5  import { Proposal, useProposals } from 'src/hooks/governance/useProposals';
  6  import { useProposalsSearch } from 'src/hooks/governance/useProposalsSearch';
  7  
  8  import { ProposalListHeader } from './ProposalListHeader';
  9  import { ProposalV3ListItem } from './ProposalV3ListItem';
 10  import { stringToState } from './StateBadge';
 11  import { VoteBar } from './VoteBar';
 12  
 13  export const ProposalsV3List = () => {
 14    const [proposalFilter, setProposalFilter] = useState<string>('all');
 15    const filterState = stringToState(proposalFilter);
 16  
 17    const [searchTerm, setSearchTerm] = useState<string>('');
 18  
 19    const { results: searchResults, loading: loadingSearchResults } = useProposalsSearch(searchTerm);
 20  
 21    const { data, isFetching: loadingProposals, fetchNextPage, hasNextPage } = useProposals();
 22  
 23    let listItems: Proposal[] = [];
 24    if (searchTerm && searchResults.length > 0) {
 25      listItems = searchResults;
 26    }
 27  
 28    if (!searchTerm && data) {
 29      data.pages.forEach((page) => listItems.push(...page.proposals));
 30    }
 31  
 32    if (proposalFilter !== 'all') {
 33      listItems = listItems.filter((proposal) => proposal.badgeState === filterState);
 34    }
 35  
 36    return (
 37      <Paper>
 38        <ProposalListHeader
 39          proposalFilter={proposalFilter}
 40          handleProposalFilterChange={setProposalFilter}
 41          handleSearchQueryChange={setSearchTerm}
 42        />
 43        {listItems.length > 0 ? (
 44          <InfiniteScroll loadMore={() => fetchNextPage()} hasMore={hasNextPage}>
 45            {listItems.map((proposal) => (
 46              <ProposalV3ListItem key={proposal.subgraphProposal.id} proposal={proposal} />
 47            ))}
 48            {loadingProposals &&
 49              Array.from({ length: 5 }).map((_, i) => <ProposalListSkeleton key={i} />)}
 50          </InfiniteScroll>
 51        ) : ((!loadingSearchResults && searchTerm) ||
 52            (!loadingProposals && proposalFilter !== 'all')) &&
 53          listItems.length === 0 ? (
 54          <NoSearchResults searchTerm={searchTerm} />
 55        ) : (
 56          Array.from({ length: 4 }).map((_, i) => <ProposalListSkeleton key={i} />)
 57        )}
 58      </Paper>
 59    );
 60  };
 61  
 62  const ProposalListSkeleton = () => {
 63    return (
 64      <Box
 65        sx={{
 66          p: 6,
 67          display: 'flex',
 68          flexWrap: 'wrap',
 69          justifyContent: 'space-between',
 70          borderBottom: (theme) => `1px solid ${theme.palette.divider}`,
 71        }}
 72      >
 73        <Stack
 74          direction="row"
 75          sx={{
 76            width: {
 77              xs: '100%',
 78              lg: '70%',
 79            },
 80            pr: { xs: 0, lg: 8 },
 81            display: 'flex',
 82            flexDirection: 'column',
 83            justifyContent: 'space-between',
 84          }}
 85        >
 86          <Stack
 87            direction="column"
 88            sx={{
 89              width: {
 90                xs: '100%',
 91                lg: '70%',
 92              },
 93              pr: { xs: 0, lg: 8 },
 94              display: 'flex',
 95              flexDirection: 'column',
 96              gap: { xs: 3, lg: 6 },
 97            }}
 98          >
 99            <Skeleton variant="rectangular" height={22} width={220} />
100            <Skeleton variant="rectangular" height={24} width={350} />
101          </Stack>
102        </Stack>
103        <Stack
104          flexGrow={1}
105          direction="column"
106          justifyContent="center"
107          sx={{
108            pl: { xs: 0, lg: 18 },
109            mt: { xs: 7, lg: 0 },
110          }}
111        >
112          <VoteBar yae percent={0} votes={0} sx={{ mb: 4 }} loading />
113          <VoteBar percent={0} votes={0} loading />
114        </Stack>
115      </Box>
116    );
117  };