@chakra-ui/react#AlertDialogBody JavaScript Examples

The following examples show how to use @chakra-ui/react#AlertDialogBody. 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: offline.js    From idena-web with MIT License 4 votes vote down vote up
export default function Offline() {
  const {t} = useTranslation()
  const {apiKeyState, apiKey, url} = useSettingsState()
  const {saveConnection} = useSettingsDispatch()
  const {coinbase, privateKey} = useAuthState()
  const router = useRouter()

  const {isOpen, onOpen, onClose} = useDisclosure()
  const cancelRef = useRef()

  const [error, setError] = useState({type: errorType.NONE})
  const [state, setState] = useState(options.BUY)
  const [step, setStep] = useState(steps.INITIAL)

  const [savedApiKey, setSavedApiKey] = useState()

  const [submitting, setSubmitting] = useState(false)

  const failToast = useFailToast()

  const {isPurchasing, savePurchase, setRestrictedKey} = useApikeyPurchasing()

  const [isDesktop] = useMediaQuery('(min-width: 481px)')
  const size = useBreakpointValue(['lg', 'md'])
  const variant = useBreakpointValue(['mobile', 'initial'])
  const variantRadio = useBreakpointValue(['mobileDark', 'dark'])
  const variantPrimary = useBreakpointValue(['primaryFlat', 'primary'])
  const variantSecondary = useBreakpointValue(['secondaryFlat', 'secondary'])

  const {data: identity} = useQuery(
    ['fetch-identity', coinbase],
    () => fetchIdentity(coinbase, true),
    {
      enabled: !!coinbase,
    }
  )

  const getKeyForCandidate = async () => {
    setSubmitting(true)

    try {
      const providers = await getAvailableProviders()
      const signature = signMessage(hexToUint8Array(coinbase), privateKey)
      const result = await getCandidateKey(
        coinbase,
        toHexString(signature, true),
        providers
      )
      savePurchase(result.id, result.provider)
    } catch (e) {
      failToast(
        `Failed to get API key for Candidate: ${
          e.response ? e.response.data : 'unknown error'
        }`
      )
    } finally {
      setSubmitting(false)
    }
  }

  const activateInvite = async () => {
    setSubmitting(true)

    try {
      const from = privateKeyToAddress(privateKey)

      const rawTx = await getRawTx(
        1,
        from,
        coinbase,
        0,
        0,
        privateKeyToPublicKey(privateKey),
        0,
        true
      )

      const tx = new Transaction().fromHex(rawTx)
      tx.sign(privateKey)

      const providers = await getAvailableProviders()

      const result = await activateKey(coinbase, `0x${tx.toHex()}`, providers)
      savePurchase(result.id, result.provider)
      sendActivateInvitation(coinbase)
    } catch (e) {
      failToast(
        `Failed to activate invite: ${
          e.response ? e.response.data : 'invitation is invalid'
        }`
      )
    } finally {
      setSubmitting(false)
    }
  }

  const process = async () => {
    switch (state) {
      case options.ENTER_KEY:
        return router.push('/settings/node')
      case options.BUY:
        return router.push('/node/rent')
      case options.ACTIVATE: {
        if (identity?.state === IdentityStatus.Invite) {
          return activateInvite()
        }
        return router.push('/node/activate')
      }
      case options.CANDIDATE:
        return getKeyForCandidate()
      case options.RESTRICTED: {
        return onOpen()
      }
      case options.RESTORE: {
        return saveConnection(savedApiKey.url, savedApiKey.key, false)
      }
      default:
    }
  }

  useEffect(() => {
    async function checkSaved() {
      try {
        const signature = signMessage(hexToUint8Array(coinbase), privateKey)
        const savedKey = await checkSavedKey(
          coinbase,
          toHexString(signature, true)
        )
        setSavedApiKey(savedKey)
      } catch (e) {}
    }
    checkSaved()
  }, [apiKey, coinbase, privateKey])

  useEffect(() => {
    if (
      apiKeyState === ApiKeyStates.ONLINE ||
      apiKeyState === ApiKeyStates.EXTERNAL
    )
      router.push('/home')
  }, [apiKeyState, router])

  useEffect(() => {
    async function check() {
      try {
        const result = await checkKey(apiKey)
        const res = await getProvider(result.provider)

        if (new URL(url).host !== new URL(res.data.url).host) {
          throw new Error()
        }

        try {
          await promiseTimeout(checkProvider(url), 2000)
          setError({type: errorType.KEY_EXPIRED})
        } catch (e) {
          setError({
            type: errorType.PROVIDER_UNAVAILABLE,
            provider: res.data.ownerName,
          })
        }
      } catch (e) {
        setError({type: errorType.NODE_UNAVAILABLE})
      }
    }

    check()
  }, [apiKey, url])

  useEffect(() => {
    if (identity?.state === IdentityStatus.Candidate) {
      setState(options.CANDIDATE)
    } else if (savedApiKey) {
      setState(options.RESTORE)
    }
  }, [identity, savedApiKey])

  const waiting = submitting || isPurchasing

  return (
    <Layout canRedirect={false}>
      <Flex
        bg={['gray.500', 'graphite.500']}
        alignItems="center"
        justifyContent="center"
        height="100%"
        direction="column"
        justify="center"
        flex="1"
      >
        <Flex
          flexGrow={1}
          align="center"
          justify={['flex-start', 'center']}
          mt="44px"
          mx={[3, 0]}
          direction="column"
        >
          <Flex
            direction="column"
            align={['center', 'initial']}
            maxWidth={['100%', '480px']}
          >
            <Flex
              direction={['column', 'row']}
              align={['center', 'flex-start']}
              textAlign={['center', 'initial']}
              w={['60%', 'auto']}
            >
              <Avatar address={coinbase} />
              <Flex
                direction="column"
                justify="center"
                flex="1"
                ml={[0, 5]}
                mt={[5, 0]}
              >
                <Heading
                  fontSize={['mdx', 'lg']}
                  fontWeight={[400, 500]}
                  color={['muted', 'white']}
                  wordBreak="break-word"
                >
                  {coinbase}
                </Heading>
              </Flex>
            </Flex>
            <Flex
              direction="column"
              mt={6}
              bg="gray.500"
              borderRadius="lg"
              px={[6, 10]}
              py={7}
              w={['100%', 'auto']}
            >
              {step === steps.INITIAL && (
                <Flex direction="column" alignItems="center" mt={6}>
                  <Flex>
                    <Text color="white" fontSize="lg">
                      {t('Offline')}
                    </Text>
                  </Flex>

                  <Flex mt={4}>
                    <Text fontSize="mdx" color="muted" textAlign="center">
                      {t('Please connect to a shared node')}
                    </Text>
                  </Flex>
                  <Flex justifyContent="center" mt={6}>
                    <PrimaryButton onClick={() => setStep(steps.CONNECT)}>
                      {t('New connection')}
                    </PrimaryButton>
                  </Flex>
                </Flex>
              )}
              {step === steps.CONNECT && (
                <>
                  <Flex justify={['center', ' flex-start']}>
                    <Text color="white" fontSize="lg">
                      {t('Connect to Idena node')}
                    </Text>
                  </Flex>

                  <Flex mt={7}>
                    <Text color="white" fontSize="sm" opacity={0.5}>
                      {t('Choose an option')}
                    </Text>
                  </Flex>
                  <Flex mt={[2, 4]}>
                    <RadioGroup w={['100%', 'auto']}>
                      <Stack direction="column" spacing={[1, 3]}>
                        {savedApiKey && savedApiKey.url !== apiKey.url && (
                          <ChooseItemRadio
                            variant={variantRadio}
                            px={[4, 0]}
                            isChecked={state === options.RESTORE}
                            onChange={() => setState(options.RESTORE)}
                            alignItems={['center', 'flex-start']}
                          >
                            <Flex direction="column" mt={['auto', '-2px']}>
                              <Text color="white">
                                {t('Restore connection')}
                              </Text>
                              <Text color="muted" fontSize="sm">
                                {savedApiKey.url}
                              </Text>
                            </Flex>
                          </ChooseItemRadio>
                        )}
                        {identity?.state === IdentityStatus.Candidate && (
                          <ChooseItemRadio
                            variant={variantRadio}
                            px={[4, 0]}
                            isChecked={state === options.CANDIDATE}
                            onChange={() => setState(options.CANDIDATE)}
                          >
                            <Text color="white">{t('Get free access')}</Text>
                          </ChooseItemRadio>
                        )}
                        <ChooseItemRadio
                          variant={variantRadio}
                          px={[4, 0]}
                          isChecked={state === options.BUY}
                          onChange={() => setState(options.BUY)}
                        >
                          <Text color="white">{t('Rent a shared node')}</Text>
                        </ChooseItemRadio>
                        <ChooseItemRadio
                          variant={variantRadio}
                          px={[4, 0]}
                          isChecked={state === options.ENTER_KEY}
                          onChange={() => setState(options.ENTER_KEY)}
                        >
                          <Text color="white">
                            {t('Enter shared node API key')}
                          </Text>
                        </ChooseItemRadio>
                        {[
                          IdentityStatus.Undefined,
                          IdentityStatus.Invite,
                        ].includes(identity?.state) && (
                          <ChooseItemRadio
                            variant={variantRadio}
                            px={[4, 0]}
                            isChecked={state === options.ACTIVATE}
                            onChange={() => setState(options.ACTIVATE)}
                          >
                            <Text color="white">
                              {t('Activate invitation')}
                            </Text>
                          </ChooseItemRadio>
                        )}
                        {identity?.state !== IdentityStatus.Candidate && (
                          <ChooseItemRadio
                            variant={variantRadio}
                            px={[4, 0]}
                            isChecked={state === options.RESTRICTED}
                            onChange={() => setState(options.RESTRICTED)}
                          >
                            <Text
                              lineHeight={['16px', 'initial']}
                              color="white"
                            >
                              {`${t('Get restricted access')}${
                                isDesktop
                                  ? ` (${t(
                                      'Can not be used for validation'
                                    ).toLocaleLowerCase()})`
                                  : ''
                              }`}
                            </Text>
                            <Text
                              display={['inline-block', 'none']}
                              color="xwhite.050"
                              fontSize="sm"
                            >
                              {t('Can not be used for validation')}
                            </Text>
                          </ChooseItemRadio>
                        )}
                      </Stack>
                    </RadioGroup>
                  </Flex>
                  <Flex mt={[4, '30px']} mb={2}>
                    <PrimaryButton
                      size={size}
                      ml="auto"
                      w={['100%', 'auto']}
                      onClick={process}
                      isDisabled={waiting}
                      isLoading={waiting}
                      loadingText="Waiting..."
                    >
                      {t('Continue')}
                    </PrimaryButton>
                  </Flex>
                </>
              )}
            </Flex>
          </Flex>

          {step === steps.INITIAL &&
            error.type === errorType.PROVIDER_UNAVAILABLE && (
              <ProviderOfflineAlert url={url} provider={error.provider} />
            )}
          {step === steps.INITIAL && error.type === errorType.KEY_EXPIRED && (
            <KeyExpiredAlert url={url} apiKey={apiKey} />
          )}
          {step === steps.INITIAL &&
            error.type === errorType.NODE_UNAVAILABLE && (
              <NodeOfflineAlert url={url} />
            )}
        </Flex>
        <Flex
          display={['none', 'flex']}
          justify="center"
          mb={8}
          direction="column"
          justifyContent="center"
        >
          <Text color="white" fontSize="mdx" opacity="0.5" mb={1}>
            {t('You can run your own node at your desktop computer.')}
          </Text>
          <TextLink
            href="https://idena.io/download"
            target="_blank"
            color="white"
            textAlign="center"
          >
            <DownloadIcon boxSize={4} mx={2} />
            {t('Download Idena')}
          </TextLink>
        </Flex>
      </Flex>
      <AlertDialog
        variant={variant}
        motionPreset="slideInBottom"
        leastDestructiveRef={cancelRef}
        onClose={onClose}
        isOpen={isOpen}
        isCentered
      >
        <AlertDialogOverlay />

        <AlertDialogContent mx={[3, 'auto']}>
          <AlertDialogHeader fontSize="lg">
            {t('Are you sure?')}
          </AlertDialogHeader>
          <AlertDialogCloseButton />
          <AlertDialogBody fontSize={['mobile', 'md']}>
            <Trans i18nKey="confirmRestrictedNodeDialog" t={t}>
              Your current API key{' '}
              <Text fontWeight="700" as="span">
                {{apiKey}}
              </Text>{' '}
              for the shared node{' '}
              <Text fontWeight="700" as="span">
                {{url}}
              </Text>{' '}
              will be lost
            </Trans>
          </AlertDialogBody>
          <AlertDialogFooter>
            <Button
              variant={variantSecondary}
              size={size}
              w={['100%', 'auto']}
              onClick={() => {
                setRestrictedKey()
                onClose()
                router.push('/home')
              }}
            >
              {t('Yes')}
            </Button>
            <Divider
              display={['block', 'none']}
              h={10}
              orientation="vertical"
              color="gray.100"
            />
            <Button
              variant={variantPrimary}
              w={['100%', 'auto']}
              size={size}
              ref={cancelRef}
              onClick={onClose}
              ml={2}
            >
              {t('Cancel')}
            </Button>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </Layout>
  )
}
Example #2
Source File: components.js    From idena-web with MIT License 4 votes vote down vote up
export function CertificateCard({
  title,
  description,
  type,
  trustLevel,
  scheduleText,
  certificateColor,
  ...props
}) {
  const {t} = useTranslation()
  const [waiting, setWaiting] = useState(false)
  const size = useBreakpointValue(['lg', 'md'])

  const {isOpen, onOpen, onClose} = useDisclosure()
  const cancelRef = useRef()

  const failToast = useFailToast()

  const testValidationState = useTestValidationState()
  const {scheduleValidation, cancelValidation} = useTestValidationDispatch()

  const epochState = useEpoch()

  const {
    isOpen: isOpenReSchedule,
    onOpen: onOpenReSchedule,
    onClose: onCloseReSchedule,
  } = useDisclosure()

  const {
    validations: {[type]: cardValue},
    current,
  } = testValidationState

  const isStarted = type === current?.type

  const schedule = async () => {
    try {
      setWaiting(true)
      if (current) {
        return failToast(
          t(
            'Can not schedule the training validation. Another validation is already requested.'
          )
        )
      }
      if (!canScheduleValidation(type, epochState?.nextValidation)) {
        return failToast(
          t(
            'Can not schedule the training validation because it overlaps with the real validation ceremony.'
          )
        )
      }
      await scheduleValidation(type)
    } catch (e) {
      console.error(e)
    } finally {
      setWaiting(false)
    }
  }

  const onScheduleClick = () => {
    if (cardValue.actionType === CertificateActionType.Passed) {
      onOpenReSchedule()
    } else {
      schedule()
    }
  }

  return (
    <Flex
      alignSelf="stretch"
      direction="column"
      shadow="0 3px 12px 0 rgba(83, 86, 92, 0.1), 0 2px 3px 0 rgba(83, 86, 92, 0.2)"
      p={['28px', 10]}
      borderRadius="lg"
      borderTop="4px solid"
      borderTopColor={certificateColor}
      {...props}
    >
      <Flex
        justify={['space-between', 'flex-start']}
        alignItems="center"
        mb={2}
      >
        <CertificateStarIcon
          order={[2, 1]}
          boxSize={[6, 4]}
          color={certificateColor}
        />
        <Heading
          order={[1, 2]}
          as="h2"
          fontSize="lg"
          fontWeight={500}
          verticalAlign="center"
          ml={[0, 1]}
        >
          {title}
        </Heading>
      </Flex>

      <Flex>
        <Text color="muted">{description}</Text>
      </Flex>
      <Flex
        direction={['column', 'row']}
        bg="gray.50"
        px={6}
        py={['30px', 5]}
        mt={6}
        rounded="lg"
      >
        <CertificateCardPanelItem title={t('Schedule')} mb={[5, 0]}>
          {isStarted
            ? dayjs(current.startTime).format('D MMM HH:mm')
            : scheduleText}
        </CertificateCardPanelItem>
        {isStarted && (
          <CertificateCardPanelItem title={t('Time left')}>
            <Countdown validationTime={current.startTime} />
          </CertificateCardPanelItem>
        )}
        <CertificateCardPanelItem title={t('Trust level')}>
          {trustLevel}
        </CertificateCardPanelItem>
      </Flex>
      {cardValue.actionType === CertificateActionType.Passed && (
        <AlertBox>
          <Flex align="center">
            <RightIcon boxSize={[5, 4]} color="green.500" mr={2} />
            <Text fontWeight={500}>{t('Passed successfully')}</Text>
          </Flex>
          <Box>
            <TextLink
              href="/try/details/[id]"
              as={`/try/details/${cardValue.id}`}
              color="green.500"
            >
              {t('Details')}
            </TextLink>
          </Box>
        </AlertBox>
      )}
      {cardValue.actionType === CertificateActionType.Failed && (
        <AlertBox borderColor="red.050" bg="red.010">
          <Flex align="center">
            <WarningIcon boxSize={[5, 4]} color="red.500" mr={2} />
            <Text fontWeight={500}>{t('Failed. Please try again')}</Text>
          </Flex>
          <Box>
            <TextLink
              href="/try/details/[id]"
              as={`/try/details/${cardValue.id}`}
              color="red.500"
            >
              {t('Details')}
            </TextLink>
          </Box>
        </AlertBox>
      )}
      {cardValue.actionType === CertificateActionType.Requested && (
        <AlertBox borderColor="gray.200" bg="gray.50">
          <Flex align="center">
            <TimerIcon boxSize={4} color="blue.500" mr={2} />
            <Text fontWeight={500}>{t('Test was requested...')}</Text>
          </Flex>
          <TextLink
            href="#"
            onClick={e => {
              e.preventDefault()
              onOpen()
            }}
          >
            {t('Cancel')}
          </TextLink>
        </AlertBox>
      )}

      <Flex mt={6}>
        <Flex
          direction={['column', 'row']}
          ml={[0, 'auto']}
          w={['100%', 'auto']}
          alignItems="center"
        >
          {cardValue.actionType === CertificateActionType.Passed && (
            <>
              <TextLink
                display={['none', 'block']}
                href="/certificate/[id]"
                as={`/certificate/${cardValue.id}`}
                fontWeight={500}
                mr={4}
                target="_blank"
              >
                <CertificateIcon boxSize={5} mr={1} />
                {t('Show certificate')}
              </TextLink>
              <Divider
                display={['none', 'block']}
                borderColor="gray.100"
                orientation="vertical"
                mr={4}
              />
            </>
          )}

          <PrimaryButton
            size={size}
            w={['100%', 'auto']}
            isDisabled={isStarted || !epochState}
            onClick={() => onScheduleClick()}
            isLoading={waiting}
            loadingText={t('Scheduling...')}
          >
            {t('Schedule')}
          </PrimaryButton>

          {cardValue.actionType === CertificateActionType.Passed && (
            <TextLink
              display={['block', 'none']}
              href="/certificate/[id]"
              as={`/certificate/${cardValue.id}`}
              fontSize="mobile"
              fontWeight={500}
              mt={5}
              target="_blank"
            >
              {t('Show certificate')}
            </TextLink>
          )}
        </Flex>
      </Flex>

      <AlertDialog
        motionPreset="slideInBottom"
        leastDestructiveRef={cancelRef}
        onClose={onClose}
        isOpen={isOpen}
        isCentered
      >
        <AlertDialogOverlay />

        <AlertDialogContent>
          <AlertDialogHeader fontSize="lg">
            {t('Cancel validation?')}
          </AlertDialogHeader>
          <AlertDialogCloseButton />
          <AlertDialogBody fontSize="md">
            {t('Are you sure you want to cancel the scheduled validation?')}
          </AlertDialogBody>
          <AlertDialogFooter>
            <SecondaryButton
              onClick={() => {
                cancelValidation(type)
                onClose()
              }}
            >
              {t('Yes')}
            </SecondaryButton>
            <PrimaryButton ref={cancelRef} onClick={onClose} ml={2}>
              {t('No')}
            </PrimaryButton>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      <ReScheduleAlert
        isOpen={isOpenReSchedule}
        onConfirm={schedule}
        onClose={onCloseReSchedule}
      />
    </Flex>
  )
}