@chakra-ui/react#Divider JavaScript Examples

The following examples show how to use @chakra-ui/react#Divider. 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: index.js    From idena-web with MIT License 6 votes vote down vote up
function ExportPK({onDialogOpen, ...props}) {
  const {t} = useTranslation()

  return (
    <Section title={t('Private key')} w={['100%', '480px']} {...props}>
      <Divider display={['none', 'block']} />
      <Flex justify="space-between" align="center" py={6}>
        <Flex>
          <PrivateKeyIcon fill="#53565C" mr={2} h={5} w={5} />
          <Text ml={[0, 3]} fontSize="mdx" fontWeight={500}>
            {t('My private key')}
          </Text>
        </Flex>
        <Flex align="center">
          <Button variant="link" color="blue.500" onClick={onDialogOpen}>
            {t('Export')}
          </Button>
        </Flex>
      </Flex>
      <Divider display={['none', 'block']} />
    </Section>
  )
}
Example #2
Source File: BlobSettingsSection.js    From blobs.app with MIT License 6 votes vote down vote up
BlobSettingsSection = () => (
  <Box px={{ lg: 10 }} py="5">
    <RandomnessSlider />
    <ComplexitySlider />
    <Divider my="5" />
    <HStack justifyContent="center" alignItems="center">
      <SolidColorPicker />
      <GradientColorsPicker />
      <PatternSetter />
      <ImageSetter />
      <OutlineToggleButton />
    </HStack>
    <Divider mt="5" />
  </Box>
)
Example #3
Source File: flip-editor.js    From idena-web with MIT License 6 votes vote down vote up
function FlipEditorToolbarDivider(props) {
  return (
    <Divider
      orientation="vertical"
      borderColor="gray.100"
      h={5}
      mx={0}
      {...props}
    />
  )
}
Example #4
Source File: FormData.js    From MeowForm with MIT License 6 votes vote down vote up
function FormData({obj}) {
    let arr = [];
    
    Object.values(obj).forEach(values => (
     arr.push(values)
    )
    )  
    

    return (
        <div>
           <Flex  justifyContent="space-between"  >

             {
                 arr.map(x=>
                    <>
                    <Text margin="5%">
                        {x}
                    </Text>
                 <Spacer/>
                    </>)
             }
            </Flex>
             <Divider margin="2%" ml="1%" colorScheme="blackAlpha"></Divider>
        </div>
    );
}
Example #5
Source File: MDXComponents.js    From benjamincarlson.io with MIT License 6 votes vote down vote up
Hr = () => {
    const { colorMode } = useColorMode()
    const borderColor = {
        light: 'gray.200',
        dark: 'gray.600'
    }

    return <Divider borderColor={borderColor[colorMode]} my={4} w="100%" />
}
Example #6
Source File: chakraMarkdownTheme.jsx    From scaffold-directory with MIT License 6 votes vote down vote up
chakraMarkdownComponents = {
  a: ({ href, children }) => (
    <Link href={href} color="blue.500">
      {children}
    </Link>
  ),
  blockquote: props => <MdBlockQuote {...props} />,
  code: props => <MdCode {...props} />,
  h1: props => <MdH1 {...props} />,
  h2: ({ children }) => (
    <Heading as="h2" size="lg" mt={6} mb={4}>
      {children}
    </Heading>
  ),
  h3: ({ children }) => (
    <Heading as="h3" size="md" mt={6} mb={4}>
      {children}
    </Heading>
  ),
  hr: () => <Divider my={6} borderBottomWidth="4px" />,
  img: props => <Image {...props} mb={4} />,
  pre: props => <MdPre {...props} />,
  p: props => <MdP {...props} />,
  ul: ({ children }) => <UnorderedList mb={4}>{children}</UnorderedList>,
}
Example #7
Source File: Header.jsx    From fastapi-react with MIT License 6 votes vote down vote up
Header = () => {
  return (
      <Flex
          as="nav"
          align="center"
          justify="space-between"
          wrap="wrap"
          padding="0.5rem"
          bg="gray.400"
      >
        <Flex align="center" mr={5}>
          <Heading as="h1" size="sm">Todos</Heading>
          <Divider />
        </Flex>
      </Flex>
  );
}
Example #8
Source File: SolidColorPicker.js    From blobs.app with MIT License 6 votes vote down vote up
SolidColorPicker = ({ type, color, switchToSolidColor }) => {
  const Picker = () => (
    <Ding
      label="Color"
      Icon={PaintIcon}
      isSelected={type === 'solid'}
      activeComp={<Box p="4px" rounded="2xl" bg={color} w="1px" />}
    />
  );

  const Content = ({ close }) => {
    const selectAndClose = (value) => {
      switchToSolidColor(value);
      close();
    };
    return (
      <Box>
        <Pallette onClick={selectAndClose} colors={defaultColors} />
        <Divider mb="4" />
        <Box p="3" pt="0">
          <Input value={color} onEnter={selectAndClose} />
        </Box>
      </Box>
    );
  };

  return (
    <Popover props={{ bg: color }} label="Choose a color" trigger={<Picker />}>
      {(close) => <Content close={close} />}
    </Popover>
  );
}
Example #9
Source File: ModalDIalog.js    From web-client with Apache License 2.0 6 votes vote down vote up
ModalDialog = ({ title, children, visible, onModalClose, style = {} }) => {

    const closeShortcutsPopup = () => {
        onModalClose();
    }

    const onKeyDownListener = useCallback((ev) => {
        if (isInputElement(document.activeElement)) {
            return;
        }

        if (ev.key === 'Escape') {
            ev.preventDefault();

            onModalClose();
        }
    }, [onModalClose]);

    useEffect(() => {
        document.addEventListener('keydown', onKeyDownListener);
        return () => {
            document.removeEventListener('keydown', onKeyDownListener);
        };
    }, [onKeyDownListener]);

    if (!visible) return null;

    return <div>
        <div className="modaldialog-backdrop" onClick={closeShortcutsPopup}></div>
        <div className="KeyboardShortcutsPopup" style={style}>
            <h3>{title}</h3>
            <Divider />

            {children}
        </div>
    </div>
}
Example #10
Source File: components.js    From idena-web with MIT License 5 votes vote down vote up
HDivider = React.forwardRef(function HDivider(props, ref) {
  return <Divider ref={ref} borderColor="gray.100" my={0} {...props} />
})
Example #11
Source File: FormHeading.js    From MeowForm with MIT License 5 votes vote down vote up
function FormHeading({obj}) {
    let arr = [];
    let temp = obj;
    const objectArray = Object.entries(temp);
    objectArray.forEach(([key, value]) => arr.push(key));


   
    

    return (
        <div>
              <Flex  justifyContent="space-between"  >
                  {
                      arr.map(key => 
                      <>
                      <Text margin="5%"
                      fontWeight="extraBold"
                      bgGradient="linear(to-l, #ec9f05 ,#ff4e00)"
                      bgClip="text">
                        <b> {key}
                        </b> 
                      </Text>
                   <Spacer/>
                      </>                      )
                  }

                  {/* {
                      objectArray.map(x=>
                         <>
                         <Text margin="5%">
                             {x}
                         </Text>
                      <Spacer/>
                         </>)
                  } */}
                 </Flex>
             <Divider margin="2%" ml="1%" colorScheme="blackAlpha"></Divider>
        </div>
    );
}
Example #12
Source File: components.js    From idena-web with MIT License 5 votes vote down vote up
function ReScheduleAlert({isOpen, onConfirm, onClose}) {
  const {t} = useTranslation()
  const size = useBreakpointValue(['lg', 'md'])
  const buttonBg = useBreakpointValue(['transparent', 'red.090'])
  const buttonBgHover = useBreakpointValue(['transparent', 'red.500'])
  const variantConfirm = useBreakpointValue(['secondaryFlat', 'primary'])
  const variantCancel = useBreakpointValue(['primaryFlat', 'secondary'])
  return (
    <Dialog isOpen={isOpen} onClose={onClose}>
      <DialogHeader>{t('Already passed successfully')}</DialogHeader>
      <DialogBody>
        {t(
          'Starting a new training validation will reset the existing training validation certificate'
        )}
      </DialogBody>
      <DialogFooter>
        <Button
          size={size}
          variant={variantCancel}
          w={['100%', 'auto']}
          onClick={onClose}
        >
          {t('Cancel')}
        </Button>
        <Divider
          display={['block', 'none']}
          h={10}
          orientation="vertical"
          color="gray.100"
        />
        <Button
          size={size}
          variant={variantConfirm}
          w={['100%', 'auto']}
          onClick={() => {
            onConfirm()
            onClose()
          }}
          backgroundColor={buttonBg}
          _hover={{
            bg: {buttonBgHover},
          }}
        >
          {t('Start anyway')}
        </Button>
      </DialogFooter>
    </Dialog>
  )
}
Example #13
Source File: KeyboardShortcuts.jsx    From web-client with Apache License 2.0 5 votes vote down vote up
KeyboardShortcuts = () => {
    const [modalVisible, setModalVisible] = useState(false);

    const onKeyDownListener = useCallback((ev) => {
        if (isInputElement(document.activeElement)) {
            return;
        }

        if (ev.key === '?') {
            ev.preventDefault();

            setModalVisible(!modalVisible);
        }
    }, [modalVisible]);

    const onModalClose = () => {
        setModalVisible(false);
    }

    useEffect(() => {
        document.addEventListener('keydown', onKeyDownListener);
        return () => {
            document.removeEventListener('keydown', onKeyDownListener);
        };
    }, [onKeyDownListener]);

    return <ModalDialog title="Keyboard shortcuts" visible={modalVisible} onModalClose={onModalClose} style={{ maxWidth: '500px' }}>
        <h4>General</h4>
        <ul>
            <li>
                Show/Hide keyboard shortcuts
                <Kbd>?</Kbd>
            </li>
            <li>
                Search
                <Kbd>/</Kbd>
            </li>
        </ul>
        <Divider />

        <h4>Pagination</h4>
        <ul>
            <li>
                Previous page
                <Kbd>p</Kbd>
            </li>
            <li>
                Next page
                <Kbd>n</Kbd>
            </li>
        </ul>
    </ModalDialog>
}
Example #14
Source File: Modal.js    From blobs.app with MIT License 5 votes vote down vote up
Modal = ({ title, src, children, actions, size = '2xl' }) => {
  const { isOpen, onOpen, onClose } = useDisclosure();
  return (
    <>
      <Box onClick={onOpen}>{src}</Box>
      <ChakModal
        isOpen={isOpen}
        onClose={onClose}
        isCentered
        motionPreset="scale"
        size={size}
        autoFocus={false}
        returnFocusOnClose={false}
      >
        <ModalOverlay background="rgba(78,86,107,0.71)" />
        <ModalContent>
          <ModalHeader px={{ base: '2', lg: '10' }}>
            <Flex align="center">
              <Flex
                direction={{ base: 'column', lg: 'row' }}
                align="center"
                justify={{ base: 'center', lg: 'space-between' }}
                flex="1"
              >
                <Heading fontSize="xl" variant="main">
                  {title}
                </Heading>
                <Box>{actions}</Box>
              </Flex>
              <Button
                onClick={onClose}
                variant="subtle"
                pos="relative"
                right={{ base: '0', lg: '-20px' }}
              >
                <CloseIcon />
              </Button>
            </Flex>
          </ModalHeader>
          <Divider />
          <ModalBody py="5" px="10">
            {typeof children === 'function' ? children() : children}
          </ModalBody>
        </ModalContent>
      </ChakModal>
    </>
  );
}
Example #15
Source File: Mdx.js    From codeursenseine.com with MIT License 5 votes vote down vote up
HR = (props) => <Divider my={8} {...props} />
Example #16
Source File: SourceCode.js    From blobs.app with MIT License 5 votes vote down vote up
SourceCode = () => {
  const links = [
    {
      name: 'blobs.app',
      icon: GithubIcon,
      link: 'https://github.com/lokesh-coder/blobs.app',
      desc: "Blobs application's source",
    },
    {
      name: 'Blob generator',
      desc: 'Create fixed blob shape using seed',
      icon: GithubIcon,
      link: 'https://github.com/lokesh-coder/blobshape',
    },
    {
      name: 'Flutter blobs',
      desc: 'Generate blobs for Flutter apps',
      icon: GithubIcon,
      link: 'https://github.com/lokesh-coder/flutter_blobs',
    },
    {
      name: 'blobshape',
      desc: 'Node package of blob generator',
      icon: NpmIcon,
      link: 'https://www.npmjs.com/package/blobshape',
    },
    {
      name: 'blobs',
      desc: 'Dart package for blob generator',
      icon: FlutterIcon,
      link: 'https://pub.dev/packages/blobs',
    },
  ];
  return (
    <Box>
      {links.map((link, index) => (
        <>
          <Box
            py="3"
            px="2"
            rounded="lg"
            _hover={{
              transform: 'scale(1.05)',
              transition: 'all 0.5s ease',
              bg: 'rgba(0,0,0,0.1)',
            }}
          >
            <LinkBox as="article">
              <Flex alignItems="center">
                <Box>
                  <link.icon fontSize="25px" color="gray.500" mr="5" />
                </Box>
                <Box flex="1" pr="2">
                  <LinkOverlay href={link.link} isExternal>
                    <Heading color="primary" fontSize="md">
                      {link.name}
                    </Heading>
                  </LinkOverlay>
                  <Text fontSize="sm">{link.desc}</Text>
                </Box>
                <Box>
                  <RightArrowIcon fontSize="20px" color="gray.400" />
                </Box>
              </Flex>
            </LinkBox>
          </Box>
          {index !== 4 && <Divider borderStyle="dashed" />}
        </>
      ))}
    </Box>
  );
}
Example #17
Source File: components.js    From idena-web with MIT License 5 votes vote down vote up
export function VotingOptionInput({
  isLast,
  isDisabled,
  onAddOption,
  onRemoveOption,
  ...props
}) {
  return (
    <React.Fragment>
      <Flex align="center" justify="space-between">
        <Stack isInline spacing={1} flex={1} py={1}>
          <Flex h={6} w={6} align="center" justify="center">
            <Box bg="muted" borderRadius="full" h={1} w={1} />
          </Flex>
          <Input
            border="none"
            px={0}
            h="auto"
            _focus={{border: 'none', outline: 'none'}}
            _placeholder={{
              color: 'muted',
            }}
            onFocus={() => {
              if (isLast) onAddOption()
            }}
            {...props}
          />
        </Stack>
        <IconButton
          icon={<CrossSmallIcon boxSize={4} />}
          isDisabled={isDisabled}
          bg="unset"
          color="muted"
          fontSize={20}
          w={5}
          minW={5}
          h={5}
          p={0}
          _hover={{
            bg: 'gray.50',
          }}
          _focus={{
            bg: 'gray.50',
          }}
          onClick={onRemoveOption}
        />
      </Flex>
      {!isLast && <Divider borderBottomColor="gray.100" mx={-1} />}
    </React.Fragment>
  )
}
Example #18
Source File: Dashboard.js    From MeowForm with MIT License 4 votes vote down vote up
Dashboard = () => {
	const { isLoading, user } = useAuth0();
	const [check] = useMediaQuery("(min-width: 1025px)");
	const { isOpen, onOpen, onClose } = useDisclosure();
	const [formName, setFormName] = React.useState();
	let userEmail = user.email;
	let apiKey = process.env.REACT_APP_APIKEY;
	let apiUrl = process.env.REACT_APP_HOSTURL;
	const [data, setData] = React.useState();
	const getData = async () => {
		let temp = await axios.get(apiUrl + "user/" + userEmail + "&" + apiKey);
		setData(temp.data[0]);
		console.log(data);
	};
	useEffect(() => {
		getData();
		if (data === undefined) {
			setTimeout(() => getData(), 2500);
		}
	}, []);
	let responses = 0;
	if (data) {
		for (let i = 0; i < data.forms.length; i++) {
			responses += data.forms[i].formData.length;
		}
	}

	const postApiData = async () => {
		let temp = await axios.post(apiUrl + "addForm/" + apiKey, {
			email: user.email,
			formName: formName,
			url: "",
		});
		getData();
	};
	const addNewForm = () => {
		if (formName === "") {
			toast.error("Form is empty?");
		} else {
			//  console.log(data.forms[0].formName);
			let isCopy = false;
			for (let i = 0; i < data.forms.length; i++) {
				if (data.forms[i].formName === formName) {
					isCopy = true;
				}
			}
			if (isCopy) {
				toast.error("form with such name already exits ");
			} else {
				postApiData();
				setTimeout(() => getData(), 2000);
				onClose();
				setTimeout(
					() => toast.success("Form Have beeen added ?"),
					2000
				);
			}
		}
	};

	return (
		<Box backgroundColor='whiteAlpha.100'>
			<Box
				padding='6'
				boxShadow='2xl'
				align='center'
				margin='2%'
				borderRadius={check ? "full" : "0 "}>
				<Flex align='center' flexDirection={check ? "row" : "column"}>
					<Flex>
						<Image src={user.picture} borderRadius='full' />
						<Text
							mt='10%'
							ml='20px'
							bgGradient='linear(to-l, #ec9f05 ,#ff4e00)'
							bgClip='text'
							fontSize={check ? "3xl" : "xl"}>
							{user.name}
						</Text>
					</Flex>

					<Flex align='center' ml={check ? "40%" : "10%"}>
						<Box>
							<Text
								bgGradient='linear(to-l, #ec9f05 ,#ff4e00)'
								bgClip='text'
								fontSize='3xl'>
								{data ? (
									responses
								) : (
									<SkeletonText></SkeletonText>
								)}
							</Text>
							<Text>Responses</Text>
						</Box>
						<Box ml='50%'>
							<Text
								bgGradient='linear(to-l, #ec9f05 ,#ff4e00)'
								bgClip='text'
								fontSize='3xl'>
								{data ? (
									data.forms.length
								) : (
									<SkeletonText></SkeletonText>
								)}
							</Text>

							<Text>Forms</Text>
						</Box>
					</Flex>
				</Flex>
			</Box>

			<Box
				padding='6'
				boxShadow='xl'
				margin='2%'
				borderRadius={check ? "25px" : "0 "}>
				<Flex justifyContent='space-between'>
					<Text
						margin='5%'
						bgGradient='linear(to-l, #ec9f05 ,#ff4e00)'
						bgClip='text'
						fontSize='3xl'>
						Forms
					</Text>
					<Button margin='5%' colorScheme='orange' onClick={onOpen}>
						New form
					</Button>
				</Flex>
				<Divider margin='2%' colorScheme='blackAlpha'></Divider>
				{data ? (
					data.forms.map((x) => (
						<FormCard
							formName={x.formName}
							responses={x.formData.length}
							formData={x.formData}
							redirectUrl={x.redirectUrl}
							email={userEmail}></FormCard>
					))
				) : (
					<>
						<SkeletonText mt='3' noOfLines={1}></SkeletonText>
						<SkeletonText mt='3' noOfLines={1}></SkeletonText>
					</>
				)}

				{data && data.forms.length === 0 ? (
					<>
						<Image
							src='https://res.cloudinary.com/dd0mtkqbr/image/upload/v1629867315/kitekat-3_dlccdn.png'
							width='25%'
							height='25%'
							ml='38%'
						/>
						<Text align='center'>
							You haven't created a form Yet{" "}
						</Text>
					</>
				) : (
					<> </>
				)}
			</Box>
			<Drawer
				onClose={onClose}
				isOpen={isOpen}
				size={check ? "xs" : "xs"}>
				<DrawerOverlay />
				<DrawerContent>
					<DrawerHeader align='center'>
						<Text
							margin='1%'
							fontWeight='extraBold'
							fontSize='3xl'
							bgGradient='linear(to-l, #ec9f05 ,#ff4e00)'
							bgClip='text'>
							Add Form
						</Text>
						<Image src='https://res.cloudinary.com/dd0mtkqbr/image/upload/v1629884425/kitekat-17_ipr2uy.png' />
						<Text></Text>
					</DrawerHeader>
					<DrawerBody>
						<Box>
							<Flex>
								<Input
									onChange={(e) =>
										setFormName(e.target.value)
									}
									placeholder='Form Name'
								/>
								<Button
									ml='0.5%'
									colorScheme='orange'
									onClick={addNewForm}>
									{" "}
									&gt;{" "}
								</Button>
							</Flex>
						</Box>
						<Box></Box>
					</DrawerBody>
				</DrawerContent>
			</Drawer>

			<Toaster />
		</Box>
	);
}
Example #19
Source File: components.js    From idena-web with MIT License 4 votes vote down vote up
export function DeferredVotes() {
  const interval = isVercelProduction ? 5 * 60 * 1000 : 60 * 1000

  const [
    {votes: pendingVotes, isReady},
    {estimateSendVote, estimateProlong, sendVote},
  ] = useDeferredVotes()
  const {t} = useTranslation()

  const failToast = useFailToast()

  const [state, setState] = useState({votes: [], index: 0})

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

  const dna = toLocaleDna(undefined, {maximumFractionDigits: 4})

  const currentVote = state.votes[state.index]

  const openModal = () => {
    if (isOpen) return
    setState({votes: pendingVotes, index: 0})
    onOpen()
  }

  const next = () => {
    if (state.index >= state.votes.length - 1) onClose()
    else {
      setState(prevState => ({...prevState, index: prevState.index + 1}))
    }
  }

  const send = async () => {
    try {
      await sendVote(currentVote, true)
    } catch (e) {
      failToast(e.message)
    } finally {
      next()
    }
  }

  const {data: txFeeData, error} = useQuery(
    ['bcn_estimateRawTx', currentVote?.contractHash],
    () => estimateSendVote(currentVote),
    {
      retry: false,
      enabled: !!currentVote,
      refetchOnWindowFocus: false,
    }
  )

  const {data: canProlong} = useQuery(
    ['bcn_estimateProlong', currentVote?.contractHash],
    () => estimateProlong(currentVote?.contractHash),
    {
      retry: false,
      enabled: !!currentVote,
      refetchOnWindowFocus: false,
    }
  )

  const {data: blockAtData} = useQuery(
    ['bcn_blockAt', currentVote?.block],
    () => getBlockAt(currentVote?.block),
    {
      enabled: !!currentVote,
      refetchOnWindowFocus: false,
    }
  )

  useInterval(
    () => {
      if (pendingVotes.length) {
        openModal()
      }
    },
    isReady ? interval : null,
    true
  )

  const size = useBreakpointValue(['mdx', 'md'])
  const variantPrimary = useBreakpointValue(['primaryFlat', 'primary'])
  const variantSecondary = useBreakpointValue(['secondaryFlat', 'secondary'])

  const errorType = getDeferredVoteErrorType(error?.message)

  return (
    <Dialog isOpen={isOpen} onClose={onClose}>
      <DialogHeader>
        {t(
          'Scheduled transaction is about to be sent ({{index}} of {{total}})',
          {
            index: state.index + 1,
            total: state.votes.length,
          }
        )}
      </DialogHeader>
      <DialogBody>
        <Stack
          bg="gray.50"
          borderRadius="md"
          px={4}
          py={3}
          spacing={[3, 3 / 2]}
        >
          <DeferredVotesModalDesc
            label={t('Date')}
            value={
              blockAtData?.timestamp
                ? `${new Date(blockAtData?.timestamp * 1000).toLocaleString(
                    undefined,
                    {
                      dateStyle: 'short',
                      timeStyle: 'short',
                    }
                  )}`
                : ''
            }
          />
          <DeferredVotesModalDesc
            label={t('Type')}
            value={t('Send public vote')}
          />
          <DeferredVotesModalDesc
            label={t('To address')}
            value={currentVote?.contractHash}
            maxValueW="50%"
          />
          <DeferredVotesModalDesc
            label={t('Amount')}
            value={dna(currentVote?.amount)}
          />
          <DeferredVotesModalDesc
            label={t('Fee')}
            value={txFeeData?.txFee ? dna(txFeeData?.txFee) : ''}
          />
        </Stack>
        <Box mt={4}>
          {(errorType === DeferredVoteErrorType.EARLY ||
            ([
              DeferredVoteErrorType.LATE,
              DeferredVoteErrorType.NOQUORUM,
            ].includes(errorType) &&
              canProlong)) && (
            <WarningAlert>
              {t(
                'Can not send the scheduled transaction yet. Please reschedule it.'
              )}
            </WarningAlert>
          )}
          {errorType === DeferredVoteErrorType.LATE && !canProlong && (
            <ErrorAlert>
              {t(
                "It's too late to send the scheduled transaction. Please delete it."
              )}
            </ErrorAlert>
          )}
          {errorType === DeferredVoteErrorType.NOQUORUM && !canProlong && (
            <ErrorAlert>
              {t('Scheduled transaction is no longer valid. Please delete it.')}
            </ErrorAlert>
          )}
        </Box>
      </DialogBody>
      <DialogFooter justify={['center', 'auto']}>
        <Button
          onClick={next}
          variant={variantSecondary}
          size={size}
          w={['100%', 'auto']}
          order={[3, 1]}
        >
          {t('Not now')}
        </Button>
        <Divider
          display={['block', 'none']}
          h={10}
          orientation="vertical"
          color="gray.100"
          order={2}
        />
        <Button
          onClick={send}
          variant={variantPrimary}
          size={size}
          w={['100%', 'auto']}
          order={[1, 2]}
        >
          {(errorType === DeferredVoteErrorType.EARLY ||
            ([
              DeferredVoteErrorType.LATE,
              DeferredVoteErrorType.NOQUORUM,
            ].includes(errorType) &&
              canProlong)) &&
            t('Reschedule')}
          {[
            DeferredVoteErrorType.LATE,
            DeferredVoteErrorType.NOQUORUM,
          ].includes(errorType) &&
            !canProlong &&
            t('Delete')}
          {errorType === DeferredVoteErrorType.NONE && t('Send')}
        </Button>
      </DialogFooter>
    </Dialog>
  )
}
Example #20
Source File: SponsorCard.js    From codeursenseine.com with MIT License 4 votes vote down vote up
SponsorCard = ({ logoSrc, link, name, excerpt, children }) => {
  const containerRef = React.useRef();
  const contentRef = React.useRef();
  const [isExpandable, setIsExpandable] = React.useState(false);
  const { isOpen, onOpen, onClose } = useDisclosure();

  React.useEffect(() => {
    if (containerRef.current && contentRef.current) {
      setIsExpandable(
        contentRef.current.offsetHeight - containerRef.current.offsetHeight > 0
      );
    }
  }, [setIsExpandable]);

  return (
    <>
      <Card
        ref={containerRef}
        as="article"
        maxH="22rem"
        position="relative"
        p={0}
      >
        <Box ref={contentRef} p={6}>
          {logoSrc && (
            <>
              <Link
                d="block"
                href={link}
                title={name}
                target="_blank"
                rel="noopener noreferrer"
              >
                <AspectRatio ratio={320 / 190}>
                  <Image src={logoSrc} alt={name} objectFit="fit" />
                </AspectRatio>
              </Link>
              <Divider />
            </>
          )}
          <Box d="flex" alignItems="baseline">
            <A href={link} title={name} target="_blank">
              {name}
            </A>
          </Box>
          <Text fontSize="sm">{excerpt}</Text>
        </Box>
        {isExpandable && (
          <Box
            position="absolute"
            bottom={0}
            left={0}
            right={0}
            pt={16}
            textAlign="center"
            background="linear-gradient(0deg, rgba(255,255,255,1) 50%, rgba(255,255,255,0) 100%)"
          >
            <Button
              onClick={onOpen}
              variant="unstyled"
              d="inline-block"
              fontSize="sm"
              h="auto"
              m={4}
              p={4}
              py={2}
              _hover={{ color: "brand.600" }}
            >
              Lire la suite
            </Button>
          </Box>
        )}
      </Card>
      <Modal motionPreset="scale" isOpen={isOpen} onClose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader fontSize="xl">
            <Box>
              <Text>{name}</Text>
            </Box>
          </ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <MDXRenderer>{children}</MDXRenderer>
          </ModalBody>
        </ModalContent>
      </Modal>
    </>
  );
}
Example #21
Source File: Todo.js    From benjamincarlson.io with MIT License 4 votes vote down vote up
Todo = () => {
    const toast = useToast()
    const { colorMode } = useColorMode()
    const { isOpen, onOpen, onClose } = useDisclosure()

    const colorSecondary = {
        light: 'gray.600',
        dark: 'gray.400',
    }

    const borderColor = {
        light: 'gray.200',
        dark: 'gray.600',
    }

    const colorSmall = {
        light: 'gray.400',
        dark: 'gray.600',
    }

    const myTodos = [
        {
            completed: false,
            title: 'Improve Final Cut Pro skills ?',
        },
        {
            completed: false,
            title: 'Finish my degree ?',
        },
        {
            completed: false,
            title: 'Grow my YouTube channel ?',
        },
        {
            completed: false,
            title: 'Grow coffeeclass.io ☕',
        },
    ]

    const [todos, setTodos] = useState(myTodos)
    const [input, setInput] = useState('')
    const removeTodo = todo => {
        setTodos(todos.filter(t => t !== todo))
    }

    const toggleCompleted = todo => {
        todo.completed = !todo.completed
        setTodos([...todos])
    }

    const addTodo = () => {
        setTodos(todos.concat({
            completed: false,
            title: input,
        }))
        setInput('')
    }

    return (
        <>
            <Box as="section" w="100%" mt={10} mb={20}>
                <Stack spacing={4} w="100%">
                    <Heading letterSpacing="tight" size="lg" fontWeight={700} as="h2">Todo List ?</Heading>
                    <Text color={colorSecondary[colorMode]}>Here is a list of things I plan to accomplish over the next year. Try it out yourself!</Text>
                    <InputGroup size="md" mt={4} borderColor="gray.500" borderColor={borderColor[colorMode]}>
                        <InputLeftElement
                            pointerEvents="none"
                            children={<Search2Icon color={useColorModeValue("gray.500", "gray.600")} />}
                        />
                        <Input
                            aria-label="Enter a Todo!"
                            placeholder="Improve Python skills ?"
                            value={input}
                            onChange={e => setInput(e.target.value)}
                        />
                        <InputRightElement width="6.75rem">
                            <Button
                                aria-label="Add a TODO!"
                                fontWeight="bold"
                                h="1.75rem"
                                size="md"
                                colorScheme="gray"
                                mr={2}
                                variant="outline"
                                px={10}
                                onClick={() => {
                                    if (input == '')
                                        toast({
                                            title: 'Whoops! There\'s an error!',
                                            description: "Input can't be empty!",
                                            status: "error",
                                            duration: 2000,
                                            isClosable: true,
                                        })
                                    else {
                                        addTodo(input)
                                    }
                                }}
                            >
                                Add Todo!
                            </Button>
                        </InputRightElement>
                    </InputGroup>
                    <Flex flexDir="column">
                        {todos.map((todo, index) => (
                            <Flex
                                key={index}
                                justify="space-between"
                                align="center"
                                my={1}
                            >
                                <Flex align="center">
                                    <Icon fontSize="xl" mr={2} as={ChevronRightIcon} color={colorSecondary[colorMode]} />
                                    <Tooltip label={`Click "${todo.title}" to mark as completed.`} placement="top" hasArrow>
                                        <Text color={colorSecondary[colorMode]} textDecor={todo.completed && "line-through"} _hover={{ cursor: 'pointer' }} onClick={() => toggleCompleted(todo)}>{todo.title}</Text>
                                    </Tooltip>
                                </Flex>
                                <Tooltip label={`Delete "${todo.title}"`} placement="top" hasArrow>
                                    <IconButton aria-label={`Delete "${todo.title}" from Todo list.`} icon={<DeleteIcon color="red.400" />} onClick={() => removeTodo(todo)} />
                                </Tooltip>
                            </Flex>
                        ))}
                    </Flex>
                    <Flex align="center">
                        <Text onClick={() => setTodos(myTodos)} _hover={{ cursor: 'pointer' }} color={colorSmall[colorMode]}>Reset</Text>
                        <Divider orientation="vertical" mx={2} h={4} />
                        <Text onClick={onOpen} _hover={{ cursor: 'pointer' }} color={colorSmall[colorMode]}>Help</Text>
                    </Flex>
                </Stack>
            </Box>
            <Modal isOpen={isOpen} onClose={onClose}>
                <ModalOverlay />
                <ModalContent>
                    <ModalHeader>Todo List Help</ModalHeader>
                    <ModalCloseButton />
                    <ModalBody>
                        <OrderedList>
                            <ListItem>
                                <Text fontWeight="bold">Add a Todo</Text>
                                <Text>Input your Todo and click the "Add Todo!" button to add a new Todo.</Text>
                            </ListItem>
                            <ListItem>
                                <Text fontWeight="bold">Reset</Text>
                                <Text>Click the "Reset" button to reset the list.</Text>
                            </ListItem>
                            <ListItem>
                                <Text fontWeight="bold">Delete</Text>
                                <Text>Click the "Delete" button to delete a Todo.</Text>
                            </ListItem>
                            <ListItem>
                                <Text fontWeight="bold">Completed</Text>
                                <Text>Click a Todo to mark it as completed.</Text>
                            </ListItem>
                            <ListItem>
                                <Text fontWeight="bold">View Code</Text>
                                <Text>Click the "View Code" button to view the code on GitHub for this simple TODO list.</Text>
                            </ListItem>
                        </OrderedList>
                        <Divider my={6} />
                        <Text><strong>Current state of Todo List:</strong> [{todos.map(t => { return `{"${t.title}",${t.completed}},` })}]</Text>
                    </ModalBody>

                    <ModalFooter>
                        <Button colorScheme="blue" mr={3} onClick={onClose}>
                            Close
                        </Button>
                        <Link
                            href="https://github.com/bjcarlson42/benjamincarlson.io/blob/master/components/Todo.js"
                            _hover={{ textDecor: 'none' }}
                            isExternal
                        >
                            <Button variant="ghost">View Code</Button>
                        </Link>
                    </ModalFooter>
                </ModalContent>
            </Modal>
        </>
    )
}
Example #22
Source File: [id].js    From idena-web with MIT License 4 votes vote down vote up
export default function Certificate({id, certificate}) {
  const {
    isOpen: isMenuOpen,
    onOpen: onMenuOpen,
    onClose: onMenuClose,
  } = useDisclosure()

  const {t} = useTranslation()

  const menuRef = useRef()

  useClickOutside(menuRef, () => {
    onMenuClose()
  })

  const {data: identity, isLoading: identityIsLoading, isFetched} = useQuery(
    ['fetch-identity', certificate.coinbase],
    () => fetchIdentity(certificate.coinbase, true),
    {
      retry: false,
      refetchOnWindowFocus: false,
    }
  )

  const identityState = identity?.state || IdentityStatus.Undefined

  return (
    <Flex
      background="rgba(17, 17, 17, 0.8)"
      flexDirection="column"
      alignItems="center"
      justifyContent="center"
      flex={1}
      height="100vh"
    >
      <Flex
        borderRadius="md"
        backgroundColor="white"
        justifyContent="center"
        px={10}
        py={8}
        direction="column"
        overflow="hidden"
        position="relative"
      >
        <CertificateTypeLabel type={certificate.type} />
        <Flex direction="column" alignItems="center" px={5}>
          <Image ignoreFallback src="/static/idena-logo-round.svg" h={16} />
          <Heading fontSize="lg" fontWeight="500" mt="45px">
            {t('Certificate')}
          </Heading>
          <Text color="muted" fontSize="md" mt={2}>
            {t('Training validation is passed successfully')}
          </Text>
          <Stack
            mt={7}
            spacing={3 / 2}
            bg="gray.50"
            px={6}
            py={4}
            rounded="lg"
            fontSize="sm"
            w={280}
          >
            <Flex justifyContent="space-between">
              <Box> {t('Short session score')}</Box>
              <Box>{toPercent(certificate.shortScore / 6)}</Box>
            </Flex>
            <Flex justifyContent="space-between">
              <Box> {t('Long session score')}</Box>
              <Box>{toPercent(certificate.longScore / 18)}</Box>
            </Flex>
            <Flex justifyContent="space-between">
              <Box> {t('Reporting score')}</Box>
              <Box>{toPercent(certificate.reportScore / 6)}</Box>
            </Flex>
          </Stack>

          <Stack isInline spacing={3} align="center" w={280} mt={8}>
            <Avatar size={8} address={certificate.coinbase} />

            <Stack spacing={0} overflow="hidden" w="100%">
              {identityIsLoading ? (
                <Skeleton h={4} w={20}></Skeleton>
              ) : (
                <Heading fontSize="md" fontWeight={500} lineHeight={4}>
                  {mapIdentityToFriendlyStatus(identityState)}
                </Heading>
              )}
              <Heading
                fontSize="sm"
                textOverflow="ellipsis"
                overflow="hidden"
                whiteSpace="nowrap"
                fontWeight={500}
                color="muted"
                lineHeight="shorter"
              >
                {certificate.coinbase}
              </Heading>
            </Stack>
            {isFetched && identityState === IdentityStatus.Undefined && (
              <Flex position="relative">
                <Icon
                  as={MdMoreVert}
                  cursor="pointer"
                  boxSize={5}
                  onClick={onMenuOpen}
                />
                <Flex
                  position="absolute"
                  borderRadius="lg"
                  py={2}
                  boxShadow="0 4px 6px 0 rgba(83, 86, 92, 0.24), 0 0 2px 0 rgba(83, 86, 92, 0.2)"
                  right={0}
                  top={6}
                  zIndex={100}
                  bg="white"
                  display={isMenuOpen ? 'flex' : 'none'}
                  ref={menuRef}
                >
                  <IconButton
                    w="100%"
                    color="brandGray.080"
                    icon={<AddUserIcon color="blue.500" boxSize={5} />}
                    _hover={{bg: 'gray.50'}}
                    _active={{bg: 'gray.50'}}
                    onClick={() => {
                      onMenuClose()
                      openExternalUrl(
                        `https://app.idena.io/dna/invite?address=${certificate.coinbase}`
                      )
                    }}
                  >
                    {t('Send invite')}
                  </IconButton>
                </Flex>
              </Flex>
            )}
          </Stack>

          <Divider mt={7}></Divider>
        </Flex>
        <Flex
          mt={16}
          justifyContent="space-between"
          w="100%"
          alignItems="center"
        >
          <Box fontSize="md" color="muted" lineHeight={4}>
            {new Date(certificate.timestamp).toLocaleDateString()}
          </Box>
          <Flex>
            <Link
              target="_blank"
              href={`https://telegram.me/share/url?url=${encodeURIComponent(
                `https://app.idena.io/certificate/${id}`
              )}&text=${encodeURIComponent(
                `I am looking for an invitation code to join Idena. Please find my ${CertificateTypeTitle(
                  certificate.type
                ).toUpperCase()} training validation certificate in the link attached.`
              )}`}
              _hover={{color: 'blue.500'}}
            >
              <TelegramIcon boxSize={5} />
            </Link>
          </Flex>
        </Flex>
      </Flex>
    </Flex>
  )
}
Example #23
Source File: BuilderProfileCard.jsx    From scaffold-directory with MIT License 4 votes vote down vote up
BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvider, fetchBuilder, userRole }) => {
  const address = useUserAddress(userProvider);
  const ens = useDisplayAddress(mainnetProvider, builder?.id);
  const [updatedSocials, setUpdatedSocials] = useState({});
  const [isUpdatingReachedOutFlag, setIsUpdatingReachedOutFlag] = useState(false);
  const [isUpdatingSocials, setIsUpdatingSocials] = useState(false);
  const { isOpen, onOpen, onClose } = useDisclosure();
  const { hasCopied, onCopy } = useClipboard(builder?.id);
  const { borderColor, secondaryFontColor } = useCustomColorModes();
  const shortAddress = ellipsizedAddress(builder?.id);
  const hasEns = ens !== shortAddress;

  const toast = useToast({ position: "top", isClosable: true });
  const toastVariant = useColorModeValue("subtle", "solid");

  const joinedDate = new Date(builder?.creationTimestamp);
  const joinedDateDisplay = joinedDate.toLocaleString("default", { month: "long" }) + " " + joinedDate.getFullYear();

  // INFO: conditional chaining and coalescing didn't work when also checking the length
  const hasProfileLinks = builder?.socialLinks ? Object.keys(builder.socialLinks).length !== 0 : false;

  const isAdmin = userRole === USER_ROLES.admin;

  useEffect(() => {
    if (builder) {
      setUpdatedSocials(builder.socialLinks ?? {});
    }
  }, [builder]);

  const handleUpdateSocials = async () => {
    setIsUpdatingSocials(true);

    // Avoid sending socials with empty strings.
    const socialLinkCleaned = Object.fromEntries(Object.entries(updatedSocials).filter(([_, value]) => !!value));

    const invalidSocials = validateSocials(socialLinkCleaned);
    if (invalidSocials.length !== 0) {
      toast({
        description: `The usernames for the following socials are not correct: ${invalidSocials
          .map(([social]) => social)
          .join(", ")}`,
        status: "error",
        variant: toastVariant,
      });
      setIsUpdatingSocials(false);
      return;
    }

    let signMessage;
    try {
      signMessage = await getUpdateSocialsSignMessage(address);
    } catch (error) {
      toast({
        description: " Sorry, the server is overloaded. ???",
        status: "error",
        variant: toastVariant,
      });
      setIsUpdatingSocials(false);
      return;
    }

    let signature;
    try {
      signature = await userProvider.send("personal_sign", [signMessage, address]);
    } catch (error) {
      toast({
        description: "Couldn't get a signature from the Wallet",
        status: "error",
        variant: toastVariant,
      });
      setIsUpdatingSocials(false);
      return;
    }

    try {
      await postUpdateSocials(address, signature, socialLinkCleaned);
    } catch (error) {
      if (error.status === 401) {
        toast({
          status: "error",
          description: "Access error",
          variant: toastVariant,
        });
        setIsUpdatingSocials(false);
        return;
      }
      toast({
        status: "error",
        description: "Can't update your socials. Please try again.",
        variant: toastVariant,
      });
      setIsUpdatingSocials(false);
      return;
    }

    toast({
      description: "Your social links have been updated",
      status: "success",
      variant: toastVariant,
    });
    fetchBuilder();
    setIsUpdatingSocials(false);
    onClose();
  };

  const handleUpdateReachedOutFlag = async reachedOut => {
    setIsUpdatingReachedOutFlag(true);

    let signMessage;
    try {
      signMessage = await getUpdateReachedOutFlagSignMessage(builder.id, reachedOut);
    } catch (error) {
      toast({
        description: " Sorry, the server is overloaded. ???",
        status: "error",
        variant: toastVariant,
      });
      setIsUpdatingReachedOutFlag(false);
      return;
    }

    let signature;
    try {
      signature = await userProvider.send("personal_sign", [signMessage, address]);
    } catch (error) {
      toast({
        description: "Couldn't get a signature from the Wallet",
        status: "error",
        variant: toastVariant,
      });
      setIsUpdatingReachedOutFlag(false);
      return;
    }

    try {
      await postUpdateReachedOutFlag(address, builder.id, reachedOut, signature);
    } catch (error) {
      if (error.status === 401) {
        toast({
          status: "error",
          description: "Access error",
          variant: toastVariant,
        });
        setIsUpdatingReachedOutFlag(false);
        return;
      }
      toast({
        status: "error",
        description: "Can't update the reached out flag. Please try again.",
        variant: toastVariant,
      });
      setIsUpdatingReachedOutFlag(false);
      return;
    }

    toast({
      description: 'Updated "reached out" flag successfully',
      status: "success",
      variant: toastVariant,
    });
    fetchBuilder();
    setIsUpdatingReachedOutFlag(false);
  };

  return (
    <>
      <BuilderProfileCardSkeleton isLoaded={!!builder}>
        {() => (
          /* delay execution */
          <Flex
            borderRadius="lg"
            borderColor={borderColor}
            borderWidth={1}
            justify={{ base: "space-around", xl: "center" }}
            direction={{ base: "row", xl: "column" }}
            p={4}
            pb={6}
            maxW={{ base: "full", lg: "50%", xl: 60 }}
            margin="auto"
          >
            <Link as={RouteLink} to={`/builders/${builder.id}`}>
              <QRPunkBlockie
                withQr={false}
                address={builder.id?.toLowerCase()}
                w={52}
                borderRadius="lg"
                margin="auto"
              />
            </Link>
            <Flex alignContent="center" direction="column" mt={4}>
              {hasEns ? (
                <>
                  <Text fontSize="2xl" fontWeight="bold" textAlign="center">
                    {ens}
                  </Text>
                  <Text textAlign="center" mb={4} color={secondaryFontColor}>
                    {shortAddress}{" "}
                    <Tooltip label={hasCopied ? "Copied!" : "Copy"} closeOnClick={false}>
                      <CopyIcon cursor="pointer" onClick={onCopy} />
                    </Tooltip>
                  </Text>
                </>
              ) : (
                <Text fontSize="2xl" fontWeight="bold" textAlign="center" mb={8}>
                  {shortAddress}{" "}
                  <Tooltip label={hasCopied ? "Copied!" : "Copy"} closeOnClick={false}>
                    <CopyIcon cursor="pointer" onClick={onCopy} />
                  </Tooltip>
                </Text>
              )}
              {isAdmin && (
                <Center mb={4}>
                  {builder.reachedOut ? (
                    <Badge variant="outline" colorScheme="green" alignSelf="center">
                      Reached Out
                    </Badge>
                  ) : (
                    <Button
                      colorScheme="green"
                      size="xs"
                      onClick={() => handleUpdateReachedOutFlag(true)}
                      isLoading={isUpdatingReachedOutFlag}
                      alignSelf="center"
                    >
                      Mark as reached out
                    </Button>
                  )}
                </Center>
              )}
              <Divider mb={6} />
              {hasProfileLinks ? (
                <Flex mb={4} justifyContent="space-evenly" alignItems="center">
                  {Object.entries(builder.socialLinks)
                    .sort(bySocialWeight)
                    .map(([socialId, socialValue]) => (
                      <SocialLink id={socialId} value={socialValue} />
                    ))}
                </Flex>
              ) : (
                isMyProfile && (
                  <Alert mb={3} status="warning">
                    <Text style={{ fontSize: 11 }}>
                      You haven't set your socials{" "}
                      <Tooltip label="It's our way of reaching out to you. We could sponsor you an ENS, offer to be part of a build or set up an ETH stream for you.">
                        <QuestionOutlineIcon />
                      </Tooltip>
                    </Text>
                  </Alert>
                )
              )}
              {isMyProfile && (
                <Button mb={3} size="xs" variant="outline" onClick={onOpen}>
                  Update socials
                </Button>
              )}
              <Text textAlign="center" color={secondaryFontColor}>
                Joined {joinedDateDisplay}
              </Text>
            </Flex>
          </Flex>
        )}
      </BuilderProfileCardSkeleton>
      <Modal isOpen={isOpen} onClose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Update your socials</ModalHeader>
          <ModalCloseButton />
          <ModalBody p={6}>
            {Object.entries(socials).map(([socialId, socialData]) => (
              <FormControl id="socialId" key={socialId} mb={3}>
                <FormLabel htmlFor={socialId} mb={0}>
                  <strong>{socialData.label}:</strong>
                </FormLabel>
                <Input
                  type="text"
                  name={socialId}
                  value={updatedSocials[socialId] ?? ""}
                  placeholder={socialData.placeholder}
                  onChange={e => {
                    const value = e.target.value;
                    setUpdatedSocials(prevSocials => ({
                      ...prevSocials,
                      [socialId]: value,
                    }));
                  }}
                />
              </FormControl>
            ))}
            <Button colorScheme="blue" onClick={handleUpdateSocials} isLoading={isUpdatingSocials} isFullWidth mt={4}>
              Update
            </Button>
          </ModalBody>
        </ModalContent>
      </Modal>
    </>
  );
}
Example #24
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>
  )
}