@chakra-ui/react#Stat JavaScript Examples

The following examples show how to use @chakra-ui/react#Stat. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: StatBox.js    From benjamincarlson.io with MIT License 6 votes vote down vote up
export default function StatBox({ title, desc, url }) {
    const { colorMode } = useColorMode()
    const borderColor = {
        light: '#CBD5E0',
        dark: '#4A5568',
    }
    const [opacity, setOpacity] = useState(0)
    
    return (
        <Link
            href={url}
            isExternal
            _hover={{
                textDecoration: 'none'
            }}
            onMouseOver={() => setOpacity(1)}
            onMouseLeave={() => setOpacity(0)}
        >
            <Box p={2} pb={[2, 1, 1]}>
                <StatGroup border={`1px solid ${borderColor[colorMode]}`} borderRadius={5} p={2} w="100%">
                    <Stat>
                        <Flex
                            align="center"
                            justifyContent="space-between"
                        >
                            <StatLabel>{desc}</StatLabel>
                            <ExternalLinkIcon opacity={opacity} />
                        </Flex>
                        <StatNumber>{title}</StatNumber>
                    </Stat>
                </StatGroup>
            </Box>
        </Link>
    )
}
Example #2
Source File: containers.js    From idena-web with MIT License 6 votes vote down vote up
export function BlockAdStat({label, value, children, ...props}) {
  return (
    <Stat {...props}>
      {label && <AdStatLabel lineHeight="4">{label}</AdStatLabel>}
      {value && <AdStatNumber>{value}</AdStatNumber>}
      {children}
    </Stat>
  )
}
Example #3
Source File: containers.js    From idena-web with MIT License 6 votes vote down vote up
export function InlineAdStat({label, value, children, ...props}) {
  const {labelWidth} = React.useContext(InlineAdGroupContext)

  return (
    <Stat flex={0} lineHeight="4" {...props}>
      <HStack>
        {label && <AdStatLabel width={labelWidth}>{label}</AdStatLabel>}
        {children || <AdStatNumber>{value || 'Any'}</AdStatNumber>}
      </HStack>
    </Stat>
  )
}
Example #4
Source File: components.js    From idena-web with MIT License 6 votes vote down vote up
export function ContactStat({label, value}) {
  return (
    <Stack as={Stat} spacing={0.5} pt={2} pb={3}>
      <StatLabel color="muted" fontSize="md">
        {label}
      </StatLabel>
      <StatNumber
        color="brandGray.500"
        fontSize="md"
        fontWeight={500}
        wordBreak="break-all"
      >
        {value}
      </StatNumber>
    </Stack>
  )
}
Example #5
Source File: components.js    From idena-web with MIT License 6 votes vote down vote up
export function MediaDnaDialogStat({label, value, children, ...props}) {
  return (
    <HStack spacing={4} align="center" bg="gray.50" px={5} py={4} {...props}>
      <Stat p={0}>
        <DnaDialogStatLabel>{label}</DnaDialogStatLabel>
        <DnaDialogStatValue>{value}</DnaDialogStatValue>
      </Stat>
      {children}
    </HStack>
  )
}
Example #6
Source File: containers.js    From idena-web with MIT License 6 votes vote down vote up
export function AsideStat({label, value, ...props}) {
  return (
    <Stat {...props}>
      <StatLabel color="muted" fontSize="md">
        {label}
      </StatLabel>
      <StatNumber fontSize="base" fontWeight={500}>
        {value}
      </StatNumber>
    </Stat>
  )
}
Example #7
Source File: components.js    From idena-web with MIT License 6 votes vote down vote up
export function ValidationReportStat({label, value, ...props}) {
  return (
    <Stat pr={0} {...props}>
      <StatLabel
        color={['gray.500', 'muted']}
        fontSize={['base', 'md']}
        fontWeight={[500, 400]}
      >
        {label}
      </StatLabel>
      <StatNumber
        fontSize={['base', 'md']}
        fontWeight={[400, 500]}
        color={['gray.300', 'gray.500']}
      >
        {value}
      </StatNumber>
    </Stat>
  )
}
Example #8
Source File: UsagePage.js    From web-client with Apache License 2.0 6 votes vote down vote up
SystemUsagePage = () => {
    const [usage] = useFetch('/system/usage');

    if (!usage) return <Loading />

    return <div>
        <div className='heading'>
            <Breadcrumb />
        </div>
        <Title type="System" title="Usage" icon={<IconDownloadDocument />} />

        <StatGroup>
            <Stat>
                <StatLabel>Attachments count</StatLabel>
                <StatNumber>{usage.attachments.total_count} total</StatNumber>
            </Stat>

            <Stat>
                <StatLabel>Attachments total disk usage</StatLabel>
                <StatNumber><FileSizeSpan fileSize={usage.attachments.total_file_size} /></StatNumber>
            </Stat>
        </StatGroup>
    </div>
}
Example #9
Source File: components.js    From idena-web with MIT License 5 votes vote down vote up
export function DnaDialogStat(props) {
  return <Stat bg="gray.50" px={5} py={4} {...props} />
}
Example #10
Source File: components.js    From idena-web with MIT License 5 votes vote down vote up
export function UserStat(props) {
  return <Stat as={Stack} spacing="3px" {...props} />
}
Example #11
Source File: view.js    From idena-web with MIT License 4 votes vote down vote up
export default function ViewVotingPage() {
  const {t, i18n} = useTranslation()

  const [, {addVote}] = useDeferredVotes()

  const toast = useToast()

  const {
    query: {id},
    push: redirect,
  } = useRouter()

  const {epoch} = useEpoch() ?? {epoch: -1}

  const {coinbase, privateKey} = useAuthState()
  const {
    data: {balance: identityBalance},
  } = useBalance()

  const [current, send, service] = useMachine(viewVotingMachine, {
    actions: {
      onError: (context, {data: {message}}) => {
        toast({
          status: 'error',
          // eslint-disable-next-line react/display-name
          render: () => (
            <Toast title={humanError(message, context)} status="error" />
          ),
        })
      },
      addVote: (_, {data: {vote}}) => addVote(vote),
    },
  })

  React.useEffect(() => {
    send('RELOAD', {id, epoch, address: coinbase})
  }, [coinbase, epoch, id, send])

  const toDna = toLocaleDna(i18n.language)

  const {
    title,
    desc,
    contractHash,
    status,
    balance = 0,
    contractBalance = Number(balance),
    votingMinPayment = 0,
    publicVotingDuration = 0,
    quorum = 20,
    committeeSize,
    options = [],
    votes = [],
    voteProofsCount,
    finishDate,
    finishCountingDate,
    selectedOption,
    winnerThreshold = 50,
    balanceUpdates,
    ownerFee,
    totalReward,
    estimatedOracleReward,
    estimatedMaxOracleReward = estimatedOracleReward,
    isOracle,
    minOracleReward,
    estimatedTotalReward,
    pendingVote,
    adCid,
    issuer,
  } = current.context

  const [
    {canProlong, canFinish, canTerminate, isFetching: actionsIsFetching},
    refetchActions,
  ] = useOracleActions(id)

  const isLoaded = !current.matches('loading')

  const sameString = a => b => areSameCaseInsensitive(a, b)

  const eitherIdleState = (...states) =>
    eitherState(current, ...states.map(s => `idle.${s}`.toLowerCase())) ||
    states.some(sameString(status))

  const isClosed = eitherIdleState(
    VotingStatus.Archived,
    VotingStatus.Terminated
  )

  const didDetermineWinner = hasWinner({
    votes,
    votesCount: voteProofsCount,
    winnerThreshold,
    quorum,
    committeeSize,
    finishCountingDate,
  })

  const isMaxWinnerThreshold = winnerThreshold === 100

  const accountableVoteCount = sumAccountableVotes(votes)

  const {data: ad} = useIpfsAd(adCid)

  const adPreviewDisclosure = useDisclosure()

  const isValidAdVoting = React.useMemo(
    () => validateAdVoting({ad, voting: current.context}) === false,
    [ad, current.context]
  )

  const isMaliciousAdVoting = ad && isValidAdVoting

  return (
    <>
      <Layout showHamburger={false}>
        <Page pt={8}>
          <Stack spacing={10}>
            <VotingSkeleton isLoaded={isLoaded} h={6}>
              <Stack isInline spacing={2} align="center">
                <VotingStatusBadge status={status} fontSize="md">
                  {t(mapVotingStatus(status))}
                </VotingStatusBadge>
                <Box
                  as={VotingBadge}
                  bg="gray.100"
                  color="muted"
                  fontSize="md"
                  cursor="pointer"
                  pl="1/2"
                  transition="color 0.2s ease"
                  _hover={{
                    color: 'brandGray.500',
                  }}
                  onClick={() => {
                    openExternalUrl(
                      `https://scan.idena.io/contract/${contractHash}`
                    )
                  }}
                >
                  <Stack isInline spacing={1} align="center">
                    <Avatar size={5} address={contractHash} />
                    <Text>{contractHash}</Text>
                  </Stack>
                </Box>
                <CloseButton
                  sx={{
                    '&': {
                      marginLeft: 'auto!important',
                    },
                  }}
                  onClick={() => redirect('/oracles/list')}
                />
              </Stack>
            </VotingSkeleton>
            <Stack isInline spacing={10} w="full">
              <Box minWidth="lg" maxW="lg">
                <Stack spacing={6}>
                  <VotingSkeleton isLoaded={isLoaded}>
                    <Stack
                      spacing={8}
                      borderRadius="md"
                      bg="gray.50"
                      py={8}
                      px={10}
                    >
                      <Stack spacing={4}>
                        <Heading
                          overflow="hidden"
                          fontSize={21}
                          fontWeight={500}
                          display="-webkit-box"
                          sx={{
                            '&': {
                              WebkitBoxOrient: 'vertical',
                              WebkitLineClamp: '2',
                            },
                          }}
                        >
                          {isMaliciousAdVoting
                            ? t('Please reject malicious ad')
                            : title}
                        </Heading>
                        {ad ? (
                          <>
                            {isMaliciousAdVoting ? (
                              <MaliciousAdOverlay>
                                <OracleAdDescription ad={ad} />
                              </MaliciousAdOverlay>
                            ) : (
                              <OracleAdDescription ad={ad} />
                            )}
                          </>
                        ) : (
                          <Text
                            isTruncated
                            lineHeight="tall"
                            whiteSpace="pre-wrap"
                          >
                            <Linkify
                              onClick={url => {
                                send('FOLLOW_LINK', {url})
                              }}
                            >
                              {desc}
                            </Linkify>
                          </Text>
                        )}
                      </Stack>
                      <Flex>
                        {adCid && (
                          <IconButton
                            icon={<ViewIcon boxSize={4} />}
                            _hover={{background: 'transparent'}}
                            onClick={adPreviewDisclosure.onOpen}
                          >
                            {t('Preview')}
                          </IconButton>
                        )}
                        <GoogleTranslateButton
                          phrases={[
                            title,
                            desc &&
                              encodeURIComponent(desc?.replace(/%/g, '%25')),
                            options.map(({value}) => value).join('\n'),
                          ]}
                          locale={i18n.language}
                          alignSelf="start"
                        />
                      </Flex>
                      <Divider orientation="horizontal" />
                      {isLoaded && <VotingPhase service={service} />}
                    </Stack>
                  </VotingSkeleton>

                  {eitherIdleState(
                    VotingStatus.Pending,
                    VotingStatus.Starting,
                    VotingStatus.Open,
                    VotingStatus.Voting,
                    VotingStatus.Voted,
                    VotingStatus.Prolonging
                  ) && (
                    <VotingSkeleton isLoaded={isLoaded}>
                      {isMaliciousAdVoting ? (
                        <>
                          {eitherIdleState(VotingStatus.Voted) ? (
                            <Box>
                              <Text color="muted" fontSize="sm" mb={3}>
                                {t('Choose an option to vote')}
                              </Text>
                              <Stack spacing={3}>
                                {/* eslint-disable-next-line no-shadow */}
                                {options.map(({id, value}) => {
                                  const isMine = id === selectedOption
                                  return (
                                    <Stack
                                      isInline
                                      spacing={2}
                                      align="center"
                                      bg={isMine ? 'blue.012' : 'gray.50'}
                                      borderRadius="md"
                                      minH={8}
                                      px={3}
                                      py={2}
                                      zIndex={1}
                                    >
                                      <Flex
                                        align="center"
                                        justify="center"
                                        bg={
                                          isMine
                                            ? 'brandBlue.500'
                                            : 'transparent'
                                        }
                                        borderRadius="full"
                                        borderWidth={isMine ? 0 : '4px'}
                                        borderColor="gray.100"
                                        color="white"
                                        w={4}
                                        h={4}
                                      >
                                        {isMine && <OkIcon boxSize={3} />}
                                      </Flex>

                                      <Text
                                        isTruncated
                                        maxW="sm"
                                        title={value.length > 50 ? value : ''}
                                      >
                                        {value}
                                      </Text>
                                    </Stack>
                                  )
                                })}
                              </Stack>
                            </Box>
                          ) : null}
                        </>
                      ) : (
                        <Box>
                          <Text color="muted" fontSize="sm" mb={3}>
                            {t('Choose an option to vote')}
                          </Text>
                          {eitherIdleState(VotingStatus.Voted) ? (
                            <Stack spacing={3}>
                              {/* eslint-disable-next-line no-shadow */}
                              {options.map(({id, value}) => {
                                const isMine = id === selectedOption
                                return (
                                  <Stack
                                    isInline
                                    spacing={2}
                                    align="center"
                                    bg={isMine ? 'blue.012' : 'gray.50'}
                                    borderRadius="md"
                                    minH={8}
                                    px={3}
                                    py={2}
                                    zIndex={1}
                                  >
                                    <Flex
                                      align="center"
                                      justify="center"
                                      bg={
                                        isMine ? 'brandBlue.500' : 'transparent'
                                      }
                                      borderRadius="full"
                                      borderWidth={isMine ? 0 : '4px'}
                                      borderColor="gray.100"
                                      color="white"
                                      w={4}
                                      h={4}
                                    >
                                      {isMine && <OkIcon boxSize={3} />}
                                    </Flex>

                                    <Text
                                      isTruncated
                                      maxW="sm"
                                      title={value.length > 50 ? value : ''}
                                    >
                                      {value}
                                    </Text>
                                  </Stack>
                                )
                              })}
                            </Stack>
                          ) : (
                            <RadioGroup
                              value={String(selectedOption)}
                              onChange={value => {
                                send('SELECT_OPTION', {
                                  option: Number(value),
                                })
                              }}
                            >
                              <Stack spacing={2}>
                                {/* eslint-disable-next-line no-shadow */}
                                {options.map(({id, value}) => (
                                  <VotingOption
                                    key={id}
                                    value={String(id)}
                                    isDisabled={eitherIdleState(
                                      VotingStatus.Pending,
                                      VotingStatus.Starting,
                                      VotingStatus.Voted
                                    )}
                                    annotation={
                                      isMaxWinnerThreshold
                                        ? null
                                        : t('{{count}} min. votes required', {
                                            count: toPercent(
                                              winnerThreshold / 100
                                            ),
                                          })
                                    }
                                  >
                                    {value}
                                  </VotingOption>
                                ))}
                              </Stack>
                            </RadioGroup>
                          )}
                        </Box>
                      )}
                    </VotingSkeleton>
                  )}

                  {eitherIdleState(
                    VotingStatus.Counting,
                    VotingStatus.Finishing,
                    VotingStatus.Archived,
                    VotingStatus.Terminating,
                    VotingStatus.Terminated
                  ) && (
                    <VotingSkeleton isLoaded={isLoaded}>
                      <Stack spacing={3}>
                        <Text color="muted" fontSize="sm">
                          {t('Voting results')}
                        </Text>
                        <VotingResult votingService={service} spacing={3} />
                      </Stack>
                    </VotingSkeleton>
                  )}

                  <VotingSkeleton isLoaded={!actionsIsFetching}>
                    <Flex justify="space-between" align="center">
                      <Stack isInline spacing={2}>
                        {eitherIdleState(VotingStatus.Pending) && (
                          <PrimaryButton
                            loadingText={t('Launching')}
                            onClick={() => {
                              send('REVIEW_START_VOTING', {
                                from: coinbase,
                              })
                            }}
                          >
                            {t('Launch')}
                          </PrimaryButton>
                        )}

                        {eitherIdleState(VotingStatus.Open) &&
                          (isOracle ? (
                            <PrimaryButton
                              onClick={() => {
                                if (isMaliciousAdVoting) {
                                  send('FORCE_REJECT')
                                }
                                send('REVIEW')
                              }}
                            >
                              {isMaliciousAdVoting ? t('Reject') : t('Vote')}
                            </PrimaryButton>
                          ) : (
                            <Box>
                              <Tooltip
                                label={t(
                                  'This vote is not available to you. Only validated identities randomly selected to the committee can vote.'
                                )}
                                placement="top"
                                zIndex="tooltip"
                              >
                                <PrimaryButton isDisabled>
                                  {t('Vote')}
                                </PrimaryButton>
                              </Tooltip>
                            </Box>
                          ))}

                        {eitherIdleState(VotingStatus.Counting) && canFinish && (
                          <PrimaryButton
                            isLoading={current.matches(
                              `mining.${VotingStatus.Finishing}`
                            )}
                            loadingText={t('Finishing')}
                            onClick={() => send('FINISH', {from: coinbase})}
                          >
                            {didDetermineWinner
                              ? t('Finish voting')
                              : t('Claim refunds')}
                          </PrimaryButton>
                        )}

                        {eitherIdleState(
                          VotingStatus.Open,
                          VotingStatus.Voting,
                          VotingStatus.Voted,
                          VotingStatus.Counting
                        ) &&
                          canProlong && (
                            <PrimaryButton
                              onClick={() => send('REVIEW_PROLONG_VOTING')}
                            >
                              {t('Prolong voting')}
                            </PrimaryButton>
                          )}

                        {(eitherIdleState(
                          VotingStatus.Voted,
                          VotingStatus.Voting
                        ) ||
                          (eitherIdleState(VotingStatus.Counting) &&
                            !canProlong &&
                            !canFinish)) && (
                          <PrimaryButton as={Box} isDisabled>
                            {t('Vote')}
                          </PrimaryButton>
                        )}

                        {!eitherIdleState(
                          VotingStatus.Terminated,
                          VotingStatus.Terminating
                        ) &&
                          canTerminate && (
                            <PrimaryButton
                              colorScheme="red"
                              variant="solid"
                              _active={{}}
                              onClick={() => send('TERMINATE')}
                            >
                              {t('Terminate')}
                            </PrimaryButton>
                          )}
                      </Stack>

                      <Stack isInline spacing={3} align="center">
                        {eitherIdleState(
                          VotingStatus.Archived,
                          VotingStatus.Terminated
                        ) &&
                          !didDetermineWinner && (
                            <Text color="red.500">
                              {t('No winner selected')}
                            </Text>
                          )}
                        <VDivider />
                        <Stack isInline spacing={2} align="center">
                          {didDetermineWinner ? (
                            <UserTickIcon color="muted" boxSize={4} />
                          ) : (
                            <UserIcon color="muted" boxSize={4} />
                          )}

                          <Text as="span">
                            {/* eslint-disable-next-line no-nested-ternary */}
                            {eitherIdleState(VotingStatus.Counting) ? (
                              <>
                                {t('{{count}} published votes', {
                                  count: accountableVoteCount,
                                })}{' '}
                                {t('out of {{count}}', {
                                  count: voteProofsCount,
                                })}
                              </>
                            ) : eitherIdleState(
                                VotingStatus.Pending,
                                VotingStatus.Open,
                                VotingStatus.Voting,
                                VotingStatus.Voted
                              ) ? (
                              t('{{count}} votes', {
                                count: voteProofsCount,
                              })
                            ) : (
                              t('{{count}} published votes', {
                                count: accountableVoteCount,
                              })
                            )}
                          </Text>
                        </Stack>
                      </Stack>
                    </Flex>
                  </VotingSkeleton>

                  <VotingSkeleton isLoaded={isLoaded}>
                    <Stack spacing={5}>
                      <Box>
                        <Text fontWeight={500}>{t('Recent transactions')}</Text>
                      </Box>
                      <Table style={{tableLayout: 'fixed', fontWeight: 500}}>
                        <Thead>
                          <Tr>
                            <RoundedTh isLeft>{t('Transaction')}</RoundedTh>
                            <RoundedTh>{t('Date and time')}</RoundedTh>
                            <RoundedTh isRight textAlign="right">
                              {t('Amount')}
                            </RoundedTh>
                          </Tr>
                        </Thead>
                        <Tbody>
                          {balanceUpdates.map(
                            ({
                              hash,
                              type,
                              timestamp,
                              from,
                              amount,
                              fee,
                              tips,
                              balanceChange = 0,
                              contractCallMethod,
                            }) => {
                              const isSender = areSameCaseInsensitive(
                                from,
                                coinbase
                              )

                              const txCost =
                                (isSender ? -amount : 0) + balanceChange
                              const totalTxCost =
                                txCost - ((isSender ? fee : 0) + tips)

                              const isCredit = totalTxCost > 0

                              const color =
                                // eslint-disable-next-line no-nested-ternary
                                totalTxCost === 0
                                  ? 'brandGray.500'
                                  : isCredit
                                  ? 'blue.500'
                                  : 'red.500'

                              return (
                                <Tr key={hash}>
                                  <OraclesTxsValueTd>
                                    <Stack isInline>
                                      <Flex
                                        align="center"
                                        justify="center"
                                        bg={isCredit ? 'blue.012' : 'red.012'}
                                        color={color}
                                        borderRadius="lg"
                                        minH={8}
                                        minW={8}
                                      >
                                        {isSender ? (
                                          <ArrowUpIcon boxSize={5} />
                                        ) : (
                                          <ArrowDownIcon boxSize={5} />
                                        )}
                                      </Flex>
                                      <Box isTruncated>
                                        {contractCallMethod ? (
                                          <Text>
                                            {
                                              ContractCallMethod[
                                                contractCallMethod
                                              ]
                                            }
                                          </Text>
                                        ) : (
                                          <Text>
                                            {ContractTransactionType[type]}
                                          </Text>
                                        )}
                                        <SmallText isTruncated title={from}>
                                          {hash}
                                        </SmallText>
                                      </Box>
                                    </Stack>
                                  </OraclesTxsValueTd>
                                  <OraclesTxsValueTd>
                                    <Text>
                                      {new Date(timestamp).toLocaleString()}
                                    </Text>
                                  </OraclesTxsValueTd>
                                  <OraclesTxsValueTd textAlign="right">
                                    <Text
                                      color={color}
                                      overflowWrap="break-word"
                                    >
                                      {toLocaleDna(i18n.language, {
                                        signDisplay: 'exceptZero',
                                      })(txCost)}
                                    </Text>
                                    {isSender && (
                                      <SmallText>
                                        {t('Fee')} {toDna(fee + tips)}
                                      </SmallText>
                                    )}
                                  </OraclesTxsValueTd>
                                </Tr>
                              )
                            }
                          )}
                          {balanceUpdates.length === 0 && (
                            <Tr>
                              <OraclesTxsValueTd colSpan={3}>
                                <FillCenter py={12}>
                                  <Stack spacing={4} align="center">
                                    <CoinsLgIcon
                                      boxSize={20}
                                      color="gray.100"
                                    />

                                    <Text color="muted">
                                      {t('No transactions')}
                                    </Text>
                                  </Stack>
                                </FillCenter>
                              </OraclesTxsValueTd>
                            </Tr>
                          )}
                        </Tbody>
                      </Table>
                    </Stack>
                  </VotingSkeleton>
                </Stack>
              </Box>
              <VotingSkeleton isLoaded={isLoaded} h={isLoaded ? 'auto' : 'lg'}>
                <Box mt={3}>
                  <Box mt={-2} mb={4}>
                    <IconButton
                      icon={<RefreshIcon boxSize={5} />}
                      px={1}
                      pr={3}
                      _focus={null}
                      onClick={() => {
                        send('REFRESH')
                        refetchActions()
                      }}
                    >
                      {t('Refresh')}
                    </IconButton>
                  </Box>
                  {!isClosed && (
                    <Stat mb={8}>
                      <StatLabel as="div" color="muted" fontSize="md">
                        <Stack isInline spacing={2} align="center">
                          <StarIcon boxSize={4} color="white" />
                          <Text fontWeight={500}>{t('Prize pool')}</Text>
                        </Stack>
                      </StatLabel>
                      <StatNumber fontSize="base" fontWeight={500}>
                        {toDna(estimatedTotalReward)}
                      </StatNumber>
                      <Box mt={1}>
                        <IconButton
                          icon={<AddFundIcon boxSize={5} />}
                          onClick={() => {
                            send('ADD_FUND')
                          }}
                        >
                          {t('Add funds')}
                        </IconButton>
                      </Box>
                    </Stat>
                  )}
                  <Stack spacing={6}>
                    {!isClosed && (
                      <Stat>
                        <StatLabel color="muted" fontSize="md">
                          <Tooltip
                            label={
                              // eslint-disable-next-line no-nested-ternary
                              Number(votingMinPayment) > 0
                                ? isMaxWinnerThreshold
                                  ? t('Deposit will be refunded')
                                  : t(
                                      'Deposit will be refunded if your vote matches the majority'
                                    )
                                : t('Free voting')
                            }
                            placement="top"
                          >
                            <Text
                              as="span"
                              borderBottom="dotted 1px"
                              borderBottomColor="muted"
                              cursor="help"
                            >
                              {t('Voting deposit')}
                            </Text>
                          </Tooltip>
                        </StatLabel>
                        <StatNumber fontSize="base" fontWeight={500}>
                          {toDna(votingMinPayment)}
                        </StatNumber>
                      </Stat>
                    )}
                    {!isClosed && (
                      <Stat>
                        <StatLabel color="muted" fontSize="md">
                          <Tooltip
                            label={t('Including your Voting deposit')}
                            placement="top"
                          >
                            <Text
                              as="span"
                              borderBottom="dotted 1px"
                              borderBottomColor="muted"
                              cursor="help"
                            >
                              {t('Min reward')}
                            </Text>
                          </Tooltip>
                        </StatLabel>
                        <StatNumber fontSize="base" fontWeight={500}>
                          {toDna(estimatedOracleReward)}
                        </StatNumber>
                      </Stat>
                    )}
                    {!isClosed && (
                      <Stat>
                        <StatLabel color="muted" fontSize="md">
                          {isMaxWinnerThreshold ? (
                            <Text as="span">{t('Your max reward')}</Text>
                          ) : (
                            <Tooltip
                              label={t(
                                `Including a share of minority voters' deposit`
                              )}
                              placement="top"
                            >
                              <Text
                                as="span"
                                borderBottom="dotted 1px"
                                borderBottomColor="muted"
                                cursor="help"
                              >
                                {t('Max reward')}
                              </Text>
                            </Tooltip>
                          )}
                        </StatLabel>
                        <StatNumber fontSize="base" fontWeight={500}>
                          {toDna(estimatedMaxOracleReward)}
                        </StatNumber>
                      </Stat>
                    )}
                    <AsideStat
                      label={t('Committee size')}
                      value={t('{{committeeSize}} oracles', {committeeSize})}
                    />
                    <AsideStat
                      label={t('Quorum required')}
                      value={t('{{count}} votes', {
                        count: quorumVotesCount({quorum, committeeSize}),
                      })}
                    />
                    <AsideStat
                      label={t('Majority threshold')}
                      value={
                        isMaxWinnerThreshold
                          ? t('N/A')
                          : toPercent(winnerThreshold / 100)
                      }
                    />
                    {isClosed && totalReward && (
                      <AsideStat
                        label={t('Prize paid')}
                        value={toDna(totalReward)}
                      />
                    )}
                  </Stack>
                </Box>
              </VotingSkeleton>
            </Stack>
          </Stack>
        </Page>
      </Layout>

      <VoteDrawer
        isOpen={
          eitherState(current, 'review', `mining.${VotingStatus.Voting}`) &&
          !eitherState(
            current,
            `mining.${VotingStatus.Voting}.reviewPendingVote`
          )
        }
        onClose={() => {
          send('CANCEL')
        }}
        // eslint-disable-next-line no-shadow
        option={options.find(({id}) => id === selectedOption)?.value}
        from={coinbase}
        to={contractHash}
        deposit={votingMinPayment}
        publicVotingDuration={publicVotingDuration}
        finishDate={finishDate}
        finishCountingDate={finishCountingDate}
        isLoading={current.matches(`mining.${VotingStatus.Voting}`)}
        onVote={() => {
          send('VOTE', {privateKey})
        }}
      />

      <AddFundDrawer
        isOpen={eitherState(
          current,
          'funding',
          `mining.${VotingStatus.Funding}`
        )}
        onClose={() => {
          send('CANCEL')
        }}
        from={coinbase}
        to={contractHash}
        available={identityBalance}
        ownerFee={ownerFee}
        isLoading={current.matches(`mining.${VotingStatus.Funding}`)}
        onAddFund={({amount}) => {
          send('ADD_FUND', {amount, privateKey})
        }}
      />

      <LaunchDrawer
        isOpen={eitherState(
          current,
          `idle.${VotingStatus.Pending}.review`,
          `mining.${VotingStatus.Starting}`
        )}
        onClose={() => {
          send('CANCEL')
        }}
        balance={contractBalance}
        requiredBalance={votingMinBalance(minOracleReward, committeeSize)}
        ownerFee={ownerFee}
        from={coinbase}
        available={identityBalance}
        isLoading={current.matches(`mining.${VotingStatus.Starting}`)}
        onLaunch={({amount}) => {
          send('START_VOTING', {amount, privateKey})
        }}
      />

      <FinishDrawer
        isOpen={eitherState(
          current,
          `idle.${VotingStatus.Counting}.finish`,
          `mining.${VotingStatus.Finishing}`
        )}
        onClose={() => {
          send('CANCEL')
        }}
        from={coinbase}
        available={identityBalance}
        isLoading={current.matches(`mining.${VotingStatus.Finishing}`)}
        onFinish={() => {
          send('FINISH', {privateKey})
        }}
        hasWinner={didDetermineWinner}
      />

      <ProlongDrawer
        isOpen={eitherState(
          current,
          'prolong',
          `mining.${VotingStatus.Prolonging}`
        )}
        onClose={() => {
          send('CANCEL')
        }}
        from={coinbase}
        available={identityBalance}
        isLoading={current.matches(`mining.${VotingStatus.Prolonging}`)}
        onProlong={() => {
          send('PROLONG_VOTING', {privateKey})
        }}
      />

      <TerminateDrawer
        isOpen={eitherState(
          current,
          `idle.terminating`,
          `mining.${VotingStatus.Terminating}`
        )}
        onClose={() => {
          send('CANCEL')
        }}
        contractAddress={contractHash}
        isLoading={current.matches(`mining.${VotingStatus.Terminating}`)}
        onTerminate={() => {
          send('TERMINATE', {privateKey})
        }}
      />

      {pendingVote && (
        <ReviewNewPendingVoteDialog
          isOpen={eitherState(
            current,
            `mining.${VotingStatus.Voting}.reviewPendingVote`
          )}
          onClose={() => {
            send('GOT_IT')
          }}
          vote={pendingVote}
          startCounting={finishDate}
          finishCounting={finishCountingDate}
        />
      )}

      {adCid && (
        <AdPreview
          ad={{...ad, author: issuer}}
          isMalicious={isMaliciousAdVoting}
          {...adPreviewDisclosure}
        />
      )}

      <Dialog
        isOpen={eitherIdleState('redirecting')}
        onClose={() => send('CANCEL')}
      >
        <DialogHeader>{t('Leaving Idena')}</DialogHeader>
        <DialogBody>
          <Text>{t(`You're about to leave Idena.`)}</Text>
          <Text>{t(`Are you sure?`)}</Text>
        </DialogBody>
        <DialogFooter>
          <SecondaryButton onClick={() => send('CANCEL')}>
            {t('Cancel')}
          </SecondaryButton>
          <PrimaryButton onClick={() => send('CONTINUE')}>
            {t('Continue')}
          </PrimaryButton>
        </DialogFooter>
      </Dialog>
    </>
  )
}
Example #12
Source File: containers.js    From idena-web with MIT License 4 votes vote down vote up
function AdPromotion({cid, title, desc, url, media, author}) {
  const {t, i18n} = useTranslation()

  const {data: burntCoins} = useBurntCoins()

  const orderedBurntCoins =
    burntCoins
      ?.sort((a, b) => b.amount - a.amount)
      .map(burn => ({...burn, ...AdBurnKey.fromHex(burn?.key)})) ?? []

  const maybeBurn = orderedBurntCoins.find(burn => burn.cid === cid)

  const formatDna = useFormatDna()

  return (
    <Stack
      spacing="10"
      bg="white"
      rounded="lg"
      px={10}
      pt={37}
      pb={44}
      w={400}
      h={660}
    >
      <Stack spacing="4">
        <Stack spacing="2">
          <Skeleton
            isLoaded={Boolean(title)}
            minH={5}
            w={title ? 'full' : 3 / 4}
          >
            <Heading
              as="h4"
              fontWeight="semibold"
              fontSize="md"
              lineHeight="5"
              isTruncated
            >
              {title}
            </Heading>
          </Skeleton>

          <Stack spacing="1.5" minH={62}>
            <Skeleton isLoaded={Boolean(desc)} minH={5}>
              <Text color="muted" fontSize="md" lineHeight="5">
                {desc}
              </Text>
            </Skeleton>
            <Skeleton isLoaded={Boolean(url)} w={1 / 4} h={4}>
              <ExternalLink
                href={url}
                fontWeight="semibold"
                display="flex"
                maxW="80"
                textProps={{h: '4', lineHeight: '4'}}
              >
                {url}
              </ExternalLink>
            </Skeleton>
          </Stack>
        </Stack>

        <LinkBox>
          <LinkOverlay href={url} isExternal>
            <AdImage src={media} w={320} />
          </LinkOverlay>
        </LinkBox>
      </Stack>
      <Stack spacing="6">
        <HStack spacing="10">
          <Stat>
            <AdStatLabel color="gray.500" fontWeight={500} lineHeight={4}>
              {t('Sponsored by')}
            </AdStatLabel>
            <AdStatNumber color="muted" fontSize="sm" mt="1.5" h="4">
              <HStack spacing="1" align="center">
                <Avatar address={author} boxSize={4} />
                <Text as="span" maxW="36" isTruncated>
                  {author}
                </Text>
              </HStack>
            </AdStatNumber>
          </Stat>
          <Stat>
            <AdStatLabel color="gray.500" fontWeight={500} lineHeight={4}>
              {t('Burnt, {{time}}', {
                time: new Intl.RelativeTimeFormat(i18n.language, {
                  style: 'short',
                }).format(24, 'hour'),
              })}
            </AdStatLabel>
            <AdStatNumber color="muted" fontSize="sm" mt="1.5" h="4">
              {formatDna(maybeBurn?.amount ?? 0)}
            </AdStatNumber>
          </Stat>
        </HStack>
        <SuccessAlert
          icon={<InfoIcon color="green.500" boxSize={5} mr={3} />}
          fontSize="md"
        >
          {t('Watching ads makes your coin valuable!')}
        </SuccessAlert>
      </Stack>
    </Stack>
  )
}