@chakra-ui/react#IconButton JavaScript Examples

The following examples show how to use @chakra-ui/react#IconButton. 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: NavSocial.js    From codeursenseine.com with MIT License 6 votes vote down vote up
NavSocial = (props) => {
  return (
    <Stack spacing="1" textAlign="center" {...props}>
      <Link href="mailto:[email protected]" fontSize="sm">
        [email protected]
      </Link>
      <Stack isInline spacing="0" justify="center" flexWrap="wrap">
        {socialLinks.map((social) => (
          <Tooltip
            key={social.link}
            zIndex="9999"
            placement="top"
            label={social.name}
          >
            <IconButton
              as="a"
              target="_blank"
              href={social.link}
              aria-label={social.name}
              icon={social.icon}
              variant="unstyled"
              size="md"
              d="inline-flex"
            />
          </Tooltip>
        ))}
      </Stack>
    </Stack>
  );
}
Example #2
Source File: ShellCommand.js    From web-client with Apache License 2.0 6 votes vote down vote up
ShellCommand = ({ children, showPrompt = true }) => {
    const codeRef = useRef();

    const handleCopy = () => {
        const code = codeRef.current.innerText

        navigator.clipboard.writeText(code).then(() => {
            actionCompletedToast('Copied to clipboard');
        }, () => {
        });
    }

    return <code className={showPrompt ? 'prompt' : ''} ref={codeRef}>
        {children}
        <IconButton onClick={handleCopy} icon={<IconDocumentDuplicate styling={{ width: "32px" }} />} />
    </code>
}
Example #3
Source File: ColorModeSwitcher.jsx    From realtime-chat-supabase-react with Apache License 2.0 6 votes vote down vote up
ColorModeSwitcher = (props) => {
  const { toggleColorMode } = useColorMode();
  const text = useColorModeValue("dark", "light");
  const SwitchIcon = useColorModeValue(FaMoon, FaSun);

  return (
    <IconButton
      size="md"
      fontSize="lg"
      aria-label={`Switch to ${text} mode`}
      variant="ghost"
      color="current"
      marginLeft="2"
      onClick={toggleColorMode}
      icon={<SwitchIcon />}
      {...props}
    />
  );
}
Example #4
Source File: DarkModeSwitch.js    From benjamincarlson.io with MIT License 6 votes vote down vote up
DarkModeSwitch = () => {
  const { colorMode, toggleColorMode } = useColorMode()
  const iconColor = {
    light: 'black',
    dark: 'white'
  }
  return (
    <IconButton
      variant="ghost"
      aria-label="Toggle dark mode"
      icon={colorMode === 'dark' ? <SunIcon /> : <MoonIcon />}
      onClick={toggleColorMode}
      color={iconColor[colorMode]}
    />
  )
}
Example #5
Source File: ColorModeSwitcher.js    From react-sample-projects with MIT License 6 votes vote down vote up
ColorModeSwitcher = props => {
  const { toggleColorMode } = useColorMode();
  const text = useColorModeValue('dark', 'light');
  const SwitchIcon = useColorModeValue(FaMoon, FaSun);

  return (
    <IconButton
      size="md"
      fontSize="lg"
      aria-label={`Switch to ${text} mode`}
      variant="ghost"
      color="current"
      marginLeft="2"
      onClick={toggleColorMode}
      icon={<SwitchIcon />}
      {...props}
    />
  );
}
Example #6
Source File: List.js    From web-client with Apache License 2.0 5 votes vote down vote up
CommandsListPage = () => {
    const navigate = useNavigate();
    const query = useQuery();
    let pageNumber = query.get('page');
    pageNumber = pageNumber !== null ? parseInt(pageNumber) : 1;
    const apiPageNumber = pageNumber - 1;

    const [numberPages, setNumberPages] = useState(1);
    const [totalCount, setTotalCount] = useState('?');

    const [commands, setCommands] = useState([]);

    const onAddCommandClick = ev => {
        ev.preventDefault();

        navigate('/commands/add');
    }

    const handlePrev = () => {
        const queryParams = new URLSearchParams();
        queryParams.set('page', pageNumber - 1);
        const url = `/commands?${queryParams.toString()}`;
        navigate(url);
    }

    const handleNext = () => {
        const queryParams = new URLSearchParams();
        queryParams.set('page', pageNumber + 1);
        const url = `/commands?${queryParams.toString()}`;
        navigate(url);
    }

    const reloadCommands = useCallback(() => {
        setCommands(null);

        const queryParams = new URLSearchParams();
        queryParams.set('page', apiPageNumber);
        const url = `/commands?${queryParams.toString()}`;

        secureApiFetch(url, { method: 'GET' })
            .then(resp => {
                if (resp.headers.has('X-Page-Count')) {
                    setNumberPages(resp.headers.get('X-Page-Count'))
                }
                if (resp.headers.has('X-Total-Count')) {
                    setTotalCount(resp.headers.get('X-Total-Count'))
                }
                return resp.json()
            })
            .then(commands => {
                setCommands(commands);
            });
    }, [setCommands, apiPageNumber]);

    const destroy = useDelete('/commands/', reloadCommands);

    useEffect(() => {
        reloadCommands()
    }, [reloadCommands])

    return <div>
        <PageTitle value="Commands" />
        <div className='heading'>
            <Breadcrumb />
            <Pagination page={apiPageNumber} total={numberPages} handlePrev={handlePrev} handleNext={handleNext} />

            <ButtonGroup isAttached>
                <CreateButton onClick={onAddCommandClick}>Add command</CreateButton>
                <Menu>
                    <MenuButton as={IconButton} aria-label='Options' icon={<FontAwesomeIcon icon={faEllipsis} />} variant='outline' />
                    <MenuList>
                        <ExportMenuItem entity="commands" />
                    </MenuList>
                </Menu>
            </ButtonGroup>
        </div>
        <Title title={`Commands (${totalCount})`} icon={<IconFolder />} />
        <CommandsTable commands={commands} onDeleteCallback={destroy} />
    </div>
}
Example #7
Source File: List.js    From web-client with Apache License 2.0 5 votes vote down vote up
ClientsList = () => {
    const navigate = useNavigate();
    const [clients, updateTasks] = useFetch('/clients')

    const destroy = useDelete('/clients/', updateTasks);

    const handleCreateClient = () => {
        navigate(`/clients/create`)
    }

    return <>
        <PageTitle value="Clients" />
        <div className='heading'>
            <Breadcrumb />

            <ButtonGroup isAttached>
                <CreateButton onClick={handleCreateClient}>Add client</CreateButton>

                <Menu>
                    <MenuButton as={IconButton} aria-label='Options' icon={<FontAwesomeIcon icon={faEllipsis} />} variant='outline' />
                    <MenuList>
                        <ExportMenuItem entity="clients" />
                    </MenuList>
                </Menu>
            </ButtonGroup>
        </div>
        <Title title='Clients' icon={<IconBriefcase />} />

        <Table>
            <Thead>
                <Tr>
                    <Th>Name</Th>
                    <Th>Address</Th>
                    <Th>URL</Th>
                    <Th>Number of contacts</Th>
                    <Th>&nbsp;</Th>
                </Tr>
            </Thead>
            <Tbody>
                {null === clients && <LoadingTableRow numColumns={5} />}
                {null !== clients && 0 === clients.length && <NoResultsTableRow numColumns={5} />}
                {null !== clients && 0 < clients.length && clients.map(client =>
                    <Tr key={client.id}>
                        <Td><ClientLink clientId={client.id}>{client.name}</ClientLink></Td>
                        <Td>{client.address || '-'}</Td>
                        <Td>{client.url ? <ExternalLink href={client.url}>{client.url}</ExternalLink> : '-'}</Td>
                        <Td>{client.num_contacts}</Td>
                        <Td textAlign="right">
                            <LinkButton href={`/clients/${client.id}/edit`}>Edit</LinkButton>
                            <DeleteIconButton onClick={() => destroy(client.id)} />
                        </Td>
                    </Tr>
                )
                }
            </Tbody>
        </Table>
    </>
}
Example #8
Source File: HtmlCodeModalButton.js    From blobs.app with MIT License 5 votes vote down vote up
HtmlCodeModalButton = ({ seed, edges, growth }) => {
  const ID = `${edges}-${growth}-${seed}`;
  const [code, setCode] = useState(null);

  const { hasCopied, onCopy } = useClipboard(code);

  const Actions = () => (
    <>
      <DownloadSVG content={code} filename={`blob_${ID}.svg`} />
      <Button
        onClick={onCopy}
        leftIcon={<CopyIcon fontSize="18px" />}
        variant="heavy"
      >
        {hasCopied ? 'Copied' : 'Copy code'}
      </Button>
    </>
  );

  const Content = () => {
    const svgEl = document.getElementById('blobSvg');
    const markup = svgEl ? formatCode(svgEl.outerHTML) : '';

    setCode(markup.replace(/^\s+|\s+$/g, ''));
    return <Highlight code={markup} lang="markup" />;
  };

  return (
    <Modal
      title="Get the code"
      src={
        <Tooltip
          label="View SVG code"
          aria-label="View SVG code"
          hasArrow
          variant="default"
        >
          <IconButton variant="ghost">
            <HtmlIcon w={6} h={6} color="gray.400" />
          </IconButton>
        </Tooltip>
      }
      actions={<Actions />}
    >
      {() => <Content />}
    </Modal>
  );
}
Example #9
Source File: FlutterCodeModalButton.js    From blobs.app with MIT License 5 votes vote down vote up
FlutterCodeModalButton = ({ edges, growth, seed }) => {
  const ID = `${edges}-${growth}-${seed}`;
  const code = `///import blobs library
import 'package:blobs/blobs.dart';
  
///add blob widget
Container(
  child: Blob.fromID(
    id: ['${ID}'],
    size: 400,
  ),
),
  `;
  const { hasCopied, onCopy } = useClipboard(ID);

  const Actions = () => (
    <>
      <Button
        onClick={onCopy}
        variant="heavy"
        leftIcon={<CopyIcon fontSize="lg" />}
      >
        {hasCopied ? 'Copied' : 'Copy ID'}
      </Button>
    </>
  );

  return (
    <Modal
      title="Use it in Flutter"
      src={
        <Tooltip
          label="Copy Flutter code"
          aria-label="Copy Flutter code"
          hasArrow
          variant="default"
        >
          <IconButton variant="ghost">
            <FlutterIcon w={6} h={6} color="gray.400" />
          </IconButton>
        </Tooltip>
      }
      actions={<Actions />}
    >
      <Highlight code={code} lang="dart" />
      <Text fontSize="sm">
        For more info about the package and documentation, please check the{' '}
        <Link href="https://pub.dev/packages/blobs/" isExternal color="primary">
          blobs
        </Link>{' '}
        repository.
      </Text>
    </Modal>
  );
}
Example #10
Source File: DeleteIconButton.js    From web-client with Apache License 2.0 5 votes vote down vote up
DeleteIconButton = (props) => <IconButton colorScheme="red" onClick={props.onClick} {...props} icon={<DeleteIcon />} />
Example #11
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 #12
Source File: CartMenu.js    From react-sample-projects with MIT License 5 votes vote down vote up
CartMenu = () => {
  const cartItems = useSelector(state => state.cart.cartItems) || [];
  const totalItems = cartItems.reduce((sum, item) => sum + item.quantity, 0);

  return (
    <Menu>
      <VStack position="relative">
        {cartItems.length > 0 && (
          <Box
            position="absolute"
            borderRadius="50%"
            right={-1}
            top={-1}
            p={1}
            zIndex={1}
            bg="red"
            color="white"
            fontSize="10"
          >
            {totalItems}
          </Box>
        )}
        <MenuButton
          as={IconButton}
          variant="ghost"
          size="md"
          fontSize="lg"
          icon={<MdShoppingCart />}
        ></MenuButton>
      </VStack>
      <MenuList p={2}>
        {cartItems.map(item => (
          <Link key={item.id} to={`/product/${item.id}`}>
            <MenuItem>
              <HStack>
                <Image
                  boxSize="2rem"
                  borderRadius="full"
                  src={item.image}
                  alt={item.title}
                  mr="12px"
                />
                <span>{item.title}</span>
              </HStack>
            </MenuItem>
          </Link>
        ))}
        {cartItems.length > 0 && (
          <MenuItem>
            <Box my={2} width="100%">
              <Link to="/cart">
                <Button isFullWidth colorScheme="teal">
                  Go To Cart
                </Button>
              </Link>
            </Box>
          </MenuItem>
        )}
        {cartItems.length === 0 && (
          <Box my={2} width="100%">
            <Text fontSize="xl">Your cart is empty :(</Text>
          </Box>
        )}
      </MenuList>
    </Menu>
  );
}
Example #13
Source File: EllipsisMenuButton.js    From web-client with Apache License 2.0 5 votes vote down vote up
EllipsisMenuButton = () => <MenuButton as={IconButton} aria-label="Options" icon={<FontAwesomeIcon icon={faEllipsis} />} variant="outline" />
Example #14
Source File: ProjectCard.js    From benjamincarlson.io with MIT License 5 votes vote down vote up
export default function ProjectCard({ title, description, repoHref, demoHref, languageColor, language, youtubeId, starCount, stargazersUrl, homepage }) {
    const [opacity, setOpacity] = useState(0)
    const [lineColor, setLineColor] = useState("blue.500")
    const { colorMode } = useColorMode()

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

    const boxShadowColor = {
        light: '0px 8px 26px rgba(0, 0, 0, 0.2)',
        dark: '0px 8px 26px rgba(0, 0, 0, 0.7)'
    }
    return (
        <Flex
            flexDir="column"
            _hover={{ transform: 'scale(1.05)', border: `2px solid ${languageColor}` }}
            transition="transform .5s ease-in-out, border .5s ease-in-out"
            boxShadow={boxShadowColor[colorMode]}
            borderRadius={5}
            border="2px solid transparent"
            onMouseOver={() => { setOpacity(1), setLineColor(languageColor) }}
            onMouseLeave={() => { setOpacity(0), setLineColor("blue.500") }}
        >
            <Flex p={[5, 15, 25]} flexDir="column" justify="space-between" h="100%">
                <Box>
                    <Heading as="h3" size="lg" fontWeight="semibold" mb={2}>{title}</Heading>
                    <Box h={1} w="35%" bgColor={lineColor} transition="background-color .5s ease-in-out" mb={4} />
                    <Text color={colorSecondary[colorMode]}>{description}</Text>
                </Box>
                <Flex justify="space-between" mt={2}>
                    <Flex align="center">

                        {stargazersUrl && (
                            <Link href={stargazersUrl.replace("api.", "").replace("repos/", "")} _hover={{ textDecor: 'none' }} isExternal>
                                <Flex opacity={opacity} transition="opacity .5s ease-in-out">
                                    <Button colorScheme="yellow" leftIcon={<AiOutlineStar />} variant="ghost">{starCount}</Button>
                                </Flex>
                            </Link>
                        )}

                        {homepage && (
                            <Link href={homepage} isExternal>
                                <IconButton icon={homepage.includes("youtu.be") ? <YoutubeIcon /> : <ExternalLinkIcon />} variant="ghost" opacity={opacity} transition="opacity .5s ease-in-out" />
                            </Link>
                        )}

                        {repoHref && (
                            <Link href={repoHref} isExternal>
                                <IconButton icon={<GitHubIcon />} variant="ghost" opacity={opacity} transition="opacity .5s ease-in-out" />
                            </Link>
                        )}
                        {demoHref && (
                            <Link href={demoHref} isExternal>
                                <IconButton icon={<ExternalLinkIcon />} variant="ghost" opacity={opacity} transition="opacity .5s ease-in-out" />
                            </Link>
                        )}
                        {youtubeId && (
                            <Link href={youtubeId} isExternal>
                                <IconButton icon={<YoutubeIcon />} variant="ghost" opacity={opacity} transition="opacity .5s ease-in-out" />
                            </Link>
                        )}
                    </Flex>
                    <Flex align="center">
                        <Box w={3} h={3} mr={1} borderRadius="50%" bgColor={languageColor} />
                        <Text fontSize="sm" color={colorSecondary[colorMode]}>{language}</Text>
                    </Flex>
                </Flex>
            </Flex>
        </Flex>
    )
}
Example #15
Source File: Reload.js    From web-client with Apache License 2.0 5 votes vote down vote up
ReloadButton = (props) => <IconButton icon={<ReloadIcon style={{ margin: 0, fill: 'white', width: 32, height: 32, stroke: 'white' }} />} title="Reload" onClick={props.onClick} {...props} style={{ textAlign: 'center', padding: 0, margin: 0 }} />
Example #16
Source File: MessageForm.jsx    From realtime-chat-supabase-react with Apache License 2.0 5 votes vote down vote up
export default function MessageForm() {
  const { supabase, username, country, auth } = useAppContext();
  const [message, setMessage] = useState("");
  const toast = useToast();
  const [isSending, setIsSending] = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setIsSending(true);
    if (!message) return;

    setMessage("");

    try {
      const { error } = await supabase.from("messages").insert([
        {
          text: message,
          username,
          country,
          is_authenticated: auth.user() ? true : false,
        },
      ]);

      if (error) {
        console.error(error.message);
        toast({
          title: "Error sending",
          description: error.message,
          status: "error",
          duration: 9000,
          isClosable: true,
        });
        return;
      }
      console.log("Sucsessfully sent!");
    } catch (error) {
      console.log("error sending message:", error);
    } finally {
      setIsSending(false);
    }
  };

  return (
    <Box py="10px" pt="15px" bg="gray.100">
      <Container maxW="600px">
        <form onSubmit={handleSubmit} autoComplete="off">
          <Stack direction="row">
            <Input
              name="message"
              placeholder="Enter a message"
              onChange={(e) => setMessage(e.target.value)}
              value={message}
              bg="white"
              border="none"
              autoFocus
            />
            <IconButton
              // variant="outline"
              colorScheme="teal"
              aria-label="Send"
              fontSize="20px"
              icon={<BiSend />}
              type="submit"
              disabled={!message}
              isLoading={isSending}
            />
          </Stack>
        </form>
        <Box fontSize="10px" mt="1">
          Warning: do not share any sensitive information, it's a public chat
          room ?
        </Box>
      </Container>
    </Box>
  );
}
Example #17
Source File: NameForm.jsx    From realtime-chat-supabase-react with Apache License 2.0 5 votes vote down vote up
export default function NameForm() {
  const { username, setUsername } = useAppContext();
  const [newUsername, setNewUsername] = useState(username);
  const [isEditing, setIsEditing] = useState(false);
  const toggleEditing = () => {
    setIsEditing(!isEditing);
  };

  const inputRef = useRef(null);

  useEffect(() => {
    if (isEditing) {
      inputRef.current.focus();
    }
  }, [isEditing]);
  useEffect(() => {
    setNewUsername(username);
  }, [username]);
  const handleSubmit = (e) => {
    e.preventDefault();
    toggleEditing();

    if (!newUsername) {
      setNewUsername(username);
      return;
    }
    // setUsername(newUsername);
    // setIsEditing(false);

    setUsername(newUsername);
    localStorage.setItem("username", newUsername);
  };

  return (
    <form onSubmit={handleSubmit} style={{ marginRight: "20px" }}>
      <Stack direction="row">
        {isEditing ? (
          <Input
            name="username"
            placeholder="Choose a username"
            onChange={(e) => setNewUsername(e.target.value)}
            value={newUsername}
            bg="gray.100"
            size="sm"
            border="none"
            onBlur={handleSubmit}
            ref={inputRef}
          />
        ) : (
          <span onClick={toggleEditing} style={{ cursor: "pointer" }}>
            Welcome <strong>{newUsername}</strong>
          </span>
        )}
        <IconButton
          size="sm"
          paddingBottom="12px"
          variant="outline"
          colorScheme="teal"
          aria-label="Save"
          fontSize="15px"
          icon={isEditing ? <BiSave /> : <BiEdit />}
          border="none"
          onClick={(e) => {
            if (isEditing) {
              handleSubmit(e);
            } else toggleEditing();
          }}
        />
      </Stack>
    </form>
  );
}
Example #18
Source File: App.js    From interspace.chat with GNU General Public License v3.0 5 votes vote down vote up
AlphaNotice = () => {
  const [toggle, setToggle] = useState(true);
  const ref = useRef(null);
  return (
    <Box
      ref={ref}
      // display="none"
      bg="linear-gradient(90.24deg, #640DFB80 0.3%, rgba(100, 13, 251, 0.1) 80.16%)"
      backdropFilter="blur(7px)"
      boxShadow="0 0 15px rgba(0,0,0,0.6)"
      color="#FF61E6"
      position="fixed"
      bottom={0}
      left={0}
      right={0}
      width="100%"
      textAlign="center"
      height="auto"
      opacity={toggle ? 1 : 0}
      transform={`translateY(${toggle ? 0 : 100}px)`}
      transition="transform 0.3s 0.2s ease-in-out, opacity 0.3s 0.3s ease-in-out"
      zIndex={3000}
    >
      <Box
        d="flex"
        position="relative"
        alignItems="center"
        justifyContent="space-around"
        flexFlow="row nowrap"
        mx="auto"
        maxW={{base: '75%', md: '66%', '2xl': "6xl"}}
        px={{base: 5, lg: 3}}
        py={3}
      >
        {/* <Image src={BabyOctoGif} boxSize="25px" objectFit="cover" /> */}
        <Text fontSize={{base: "2vmin", lg: '0.7vmax'}} fontWeight={700}>
          The site is in{" "}
          <Text as="span" color="#76EBF2" fontWeight="700">
            Alpha
          </Text>
          .{" "}
          <span role="img" aria-label="watchful eyes">
            ?
          </span>{" "}
          We're still working on content, there's no Web3 connectivity and there
          are some bugs. <br /> We're working to get it
          all ship shape for June!
        </Text>
        {/* <Image src={BabyOctoGif} boxSize="35px" objectFit="cover" /> */}
        <IconButton
          onClick={() => setToggle(!toggle)}
          colorScheme="ghost"
          color="#927CFF"
          pos="fixed"
          bottom={3}
          right={{base: 2, lg: 6}}
          size="sm"
          aria-label="Close easter egg"
          icon={<CloseIcon />}
          zIndex={2001}
        />
      </Box>
    </Box>
  );
}
Example #19
Source File: pagination.js    From react-table-library with MIT License 5 votes vote down vote up
Component = () => {
  const data = { nodes };

  const chakraTheme = getTheme(DEFAULT_OPTIONS);
  const theme = useTheme(chakraTheme);

  const pagination = usePagination(data, {
    state: {
      page: 0,
      size: 2,
    },
    onChange: onPaginationChange,
  });

  function onPaginationChange(action, state) {
    console.log(action, state);
  }

  const COLUMNS = [
    { label: 'Task', renderCell: (item) => item.name },
    {
      label: 'Deadline',
      renderCell: (item) =>
        item.deadline.toLocaleDateString('en-US', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
        }),
    },
    { label: 'Type', renderCell: (item) => item.type },
    {
      label: 'Complete',
      renderCell: (item) => item.isComplete.toString(),
    },
    { label: 'Tasks', renderCell: (item) => item.nodes?.length },
  ];

  return (
    <>
      <Box p={3} borderWidth="1px" borderRadius="lg">
        <CompactTable columns={COLUMNS} data={data} theme={theme} pagination={pagination} />
      </Box>

      <br />
      <HStack justify="flex-end">
        <IconButton
          aria-label="previous page"
          icon={<FaChevronLeft />}
          colorScheme="teal"
          variant="ghost"
          disabled={pagination.state.page === 0}
          onClick={() => pagination.fns.onSetPage(pagination.state.page - 1)}
        />

        {pagination.state.getPages(data.nodes).map((_, index) => (
          <Button
            key={index}
            colorScheme="teal"
            variant={pagination.state.page === index ? 'solid' : 'ghost'}
            onClick={() => pagination.fns.onSetPage(index)}
          >
            {index + 1}
          </Button>
        ))}
        <IconButton
          aria-label="next page"
          icon={<FaChevronRight />}
          colorScheme="teal"
          variant="ghost"
          disabled={pagination.state.page + 1 === pagination.state.getTotalPages(data.nodes)}
          onClick={() => pagination.fns.onSetPage(pagination.state.page + 1)}
        />
      </HStack>

      <br />
      <DocumentationSee anchor={'Features/' + key} />
    </>
  );
}
Example #20
Source File: SpeakerCard.js    From codeursenseine.com with MIT License 5 votes vote down vote up
SpeakerCard = ({ speaker }) => {
  const {
    name,
    image: { publicURL },
    company,
    twitterLink,
    githubLink,
  } = speaker?.childMdx?.frontmatter;

  const { body } = speaker?.childMdx;

  return (
    <Card borderLeftWidth={2} borderLeftColor="brand.600">
      <Flex>
        <Box mr={4}>
          <AspectRatio ratio={1} w="6em" maxW="100%">
            <Image src={publicURL} borderRadius={4} />
          </AspectRatio>
        </Box>
        <Box>
          <Heading fontSize="lg">{name}</Heading>
          <Heading fontSize="md">{company}</Heading>
          {twitterLink && (
            <IconButton
              as="a"
              target="_blank"
              href={twitterLink}
              title={`${name} Twitter`}
              icon={<FaTwitter />}
              variant="ghost"
              colorScheme="brand"
              rel="noopener noreferrer"
            />
          )}
          {githubLink && (
            <IconButton
              as="a"
              target="_blank"
              href={githubLink}
              title={`${name} Github`}
              icon={<FaGithub />}
              variant="ghost"
              colorScheme="brand"
              rel="noopener noreferrer"
            />
          )}
        </Box>
      </Flex>
      {body && (
        <Box mt={4}>
          <MDXRenderer mt={4}>{body}</MDXRenderer>
        </Box>
      )}
    </Card>
  );
}
Example #21
Source File: NavTopbar.js    From codeursenseine.com with MIT License 5 votes vote down vote up
NavTopbar = ({ onNavOpen = () => {}, ...props }) => {
  const theme = useTheme();

  const data = useStaticQuery(graphql`
    query NavTopbarQuery {
      site {
        siteMetadata {
          currentYear
        }
      }
    }
  `);

  return (
    <Flex
      as="nav"
      display={{ base: "flex", md: "none" }}
      background={theme.gradients.brand}
      justifyContent="space-between"
      color="white"
      position="fixed"
      top="0"
      left="0"
      right="0"
      zIndex="2"
      align="center"
      {...props}
    >
      <Link to={`/${data.site.siteMetadata.currentYear}`}>
        <Logo w="4.5" h="2.5rem" pl="2" />
      </Link>
      <Box textAlign="center">
        <Text fontFamily="heading" fontSize="0.6rem">
          {theme.data.pretitle}
        </Text>
        <Heading as="h4" size="xs" fontSize="0.7rem">
          {theme.data.title}
        </Heading>
      </Box>
      <IconButton
        variant="unstyled"
        aria-label="Menu"
        d="inline-flex"
        icon={<FiMenu />}
        size="lg"
        onClick={() => onNavOpen()}
      />
    </Flex>
  );
}
Example #22
Source File: Nav.js    From codeursenseine.com with MIT License 4 votes vote down vote up
Nav = ({
  breakpoint,
  isOpen,
  onNavClose = () => {},
  ...props
}) => {
  const theme = useTheme();
  const { pathname } = useLocation();

  const data = useStaticQuery(graphql`
    query NavPagesQuery {
      site {
        siteMetadata {
          currentYear
        }
      }
    }
  `);

  const currentYear = data.site.siteMetadata.currentYear;

  return (
    <Flex
      direction="column"
      alignItems={{ [breakpoint]: "flex-end" }}
      background={theme.gradients.brand}
      color="white"
      position="fixed"
      top="0"
      left="0"
      bottom="0"
      transform={{
        base: `translate(${isOpen ? 0 : "100%"})`,
        [breakpoint]: "none",
      }}
      transition={{ base: "transform 0.4s", [breakpoint]: "none" }}
      overflowY="auto"
      overflowX="none"
      zIndex="3"
      as="nav"
      {...props}
    >
      <Flex direction="column" flexGrow={1}>
        <IconButton
          variant="unstyled"
          aria-label="Menu"
          d={{ base: "inline-flex", [breakpoint]: "none" }}
          icon={<FiX />}
          size="lg"
          position="absolute"
          top="0"
          right="0"
          onClick={() => onNavClose()}
        />
        <Stack px="2">
          <Flex
            px="2"
            pt="4vh"
            pb="2vh"
            align="center"
            justify={{ base: "center", [breakpoint]: "flex-end" }}
          >
            <Link to={`/${currentYear}`}>
              <Logo w={{ base: "8rem", [breakpoint]: "12rem" }} />
            </Link>
          </Flex>
          <Stack>
            <NavLink isMain as={Link} to={`/${currentYear}`}>
              Édition {currentYear}
            </NavLink>
            {pathname.startsWith(withPrefix(`/${currentYear}`)) && (
              <>
                {/* <NavLink as={Link} to={`/${currentYear}/programme`}>
                  Programme
                </NavLink>
                <NavLink as={Link} to={`/${currentYear}/speakers`}>
                  Intervenants
                </NavLink> */}
                <NavLink as={Link} to={`/${currentYear}/sponsors`}>
                  Sponsors
                </NavLink>
                <NavLink as={Link} to={`/${currentYear}/organisateurs`}>
                  Organisateurs
                </NavLink>
                {/* <NavLink as={Link} to={`/${currentYear}/kit-de-presse`}>
                  Kit de presse
                </NavLink> */}
                <NavLink as={Link} to={`/${currentYear}/code-of-conduct`}>
                  Code de conduite
                </NavLink>
                <NavLink as={Link} to={`/${currentYear}/review-2020-2021`}>
                  Review 2020-2021
                </NavLink>
              </>
            )}
          </Stack>
          <Stack spacing="0">
            <NavLink isMain as={Link} to="/meetups">
              Meetups
            </NavLink>
            {pathname.startsWith(withPrefix("/meetups")) && (
              <>
                <NavLink as={Link} to="/meetups/sponsors">
                  Sponsors
                </NavLink>
              </>
            )}
          </Stack>
          <Stack>
            <NavLink isMain as={Link} to="/live" title="Live Twitch">
              <span role="img" aria-label="Red circle">
                ?
              </span>{" "}
              Live Stream
            </NavLink>
          </Stack>
          <Stack>
            <NavLink isMain as={Link} to="/devoxx4kids" title="Devoxx4Kids">
              Devoxx4Kids
            </NavLink>
          </Stack>
        </Stack>
        <Stack mt="auto" p="4" mb="2">
          <NavSocial />
          <NavPreviousYears />
        </Stack>
      </Flex>
    </Flex>
  );
}
Example #23
Source File: Details.js    From web-client with Apache License 2.0 4 votes vote down vote up
ProjectDetails = () => {
    const navigate = useNavigate();
    const { projectId } = useParams();
    const { colorMode } = useColorMode()

    const [project, updateProject] = useFetch(`/projects/${projectId}`)
    const [users] = useFetch(`/projects/${projectId}/users`)
    const destroy = useDelete(`/projects/`, updateProject);

    const handleGenerateReport = () => {
        navigate(`/projects/${project.id}/report`)
    }

    const handleManageTeam = () => {
        navigate(`/projects/${project.id}/membership`)
    }

    const onArchiveButtonClick = (project) => {
        secureApiFetch(`/projects/${project.id}`, {
            method: 'PATCH',
            body: JSON.stringify({ archived: !project.archived })
        })
            .then(() => {
                updateProject();
                actionCompletedToast('The project has been updated.');
            })
            .catch(err => console.error(err))
    }

    if (project && project.is_template) {
        return <Navigate to={`/projects/templates/${project.id}`} />
    }

    return <>
        <div className='heading'>
            <Breadcrumb>
                <Link to="/projects">Projects</Link>
            </Breadcrumb>
            {project && <>
                <PageTitle value={`${project.name} project`} />
                <ProjectTeam project={project} users={users} />

                <ButtonGroup isAttached>
                    <RestrictedComponent roles={['administrator', 'superuser', 'user']}>
                        {!project.archived && <>
                            <LinkButton href={`/projects/${project.id}/edit`}>Edit</LinkButton>
                            <SecondaryButton onClick={handleGenerateReport} leftIcon={<IconClipboardCheck />}>Report</SecondaryButton>
                            <SecondaryButton onClick={handleManageTeam} leftIcon={<IconUserGroup />}>Membership</SecondaryButton>
                        </>}

                        <Menu>
                            <MenuButton as={IconButton} aria-label='Options' icon={<FontAwesomeIcon icon={faEllipsis} />} variant='outline' />
                            <MenuList>
                                <MenuItem onClick={() => onArchiveButtonClick(project)}>{project.archived ? 'Unarchive' : 'Archive'}</MenuItem>
                                <MenuItem icon={<FontAwesomeIcon icon={faTrash} />} color={colorMode === "light" ? "red.500" : "red.400"} onClick={() => destroy(project.id)}>Delete</MenuItem>
                            </MenuList>
                        </Menu>
                    </RestrictedComponent>
                </ButtonGroup>
            </>}
        </div>
        {!project ? <Loading /> :
            <>
                <Title title={project.name} type="Project" icon={<IconFolder />} />

                <Tabs>
                    <TabList>
                        <Tab>Details</Tab>
                        <Tab>Targets</Tab>
                        <Tab>Tasks</Tab>
                        <Tab>Vulnerabilities</Tab>
                        <Tab>Notes</Tab>
                        <Tab>Attachments</Tab>
                        <Tab>Vault</Tab>
                    </TabList>
                    <TabPanels>
                        <TabPanel><ProjectDetailsTab project={project} /></TabPanel>
                        <TabPanel><ProjectTargets project={project} /></TabPanel>
                        <TabPanel><ProjectTasks project={project} /></TabPanel>
                        <TabPanel><ProjectVulnerabilities project={project} /></TabPanel>
                        <TabPanel><ProjectNotesTab project={project} /></TabPanel>
                        <TabPanel><ProjectAttachmentsTab project={project} /></TabPanel>
                        <TabPanel><ProjectVaultTab project={project} /></TabPanel>
                    </TabPanels>
                </Tabs>
            </>
        }
    </>
}
Example #24
Source File: showreel.js    From react-table-library with MIT License 4 votes vote down vote up
Component = () => {
  const [data, setData] = React.useState({ nodes });

  //* Theme *//

  const chakraTheme = getTheme({
    ...DEFAULT_OPTIONS,
    striped: true,
  });
  const customTheme = {
    Table: `
      --data-table-library_grid-template-columns:  64px repeat(5, minmax(0, 1fr));

      margin: 16px 0px;
    `,
  };
  const theme = useTheme([chakraTheme, customTheme]);

  //* Resize *//

  const resize = { resizerHighlight: '#dee2e6' };

  //* Pagination *//

  const pagination = usePagination(data, {
    state: {
      page: 0,
      size: 4,
    },
    onChange: onPaginationChange,
  });

  function onPaginationChange(action, state) {
    console.log(action, state);
  }

  //* Search *//

  const [search, setSearch] = React.useState('');

  useCustom('search', data, {
    state: { search },
    onChange: onSearchChange,
  });

  function onSearchChange(action, state) {
    console.log(action, state);
    pagination.fns.onSetPage(0);
  }

  //* Filter *//

  const [isHide, setHide] = React.useState(false);

  useCustom('filter', data, {
    state: { isHide },
    onChange: onFilterChange,
  });

  function onFilterChange(action, state) {
    console.log(action, state);
    pagination.fns.onSetPage(0);
  }

  //* Select *//

  const select = useRowSelect(data, {
    onChange: onSelectChange,
  });

  function onSelectChange(action, state) {
    console.log(action, state);
  }

  //* Tree *//

  const tree = useTree(
    data,
    {
      onChange: onTreeChange,
    },
    {
      clickType: TreeExpandClickTypes.ButtonClick,
      treeYLevel: 1,
      treeIcon: {
        margin: '4px',
        iconDefault: null,
        iconRight: <FaChevronRight />,
        iconDown: <FaChevronDown />,
      },
    },
  );

  function onTreeChange(action, state) {
    console.log(action, state);
  }

  //* Sort *//

  const sort = useSort(
    data,
    {
      onChange: onSortChange,
    },
    {
      sortIcon: {
        iconDefault: null,
        iconUp: <FaChevronUp />,
        iconDown: <FaChevronDown />,
      },
      sortFns: {
        TASK: (array) => array.sort((a, b) => a.name.localeCompare(b.name)),
        DEADLINE: (array) => array.sort((a, b) => a.deadline - b.deadline),
        TYPE: (array) => array.sort((a, b) => a.type.localeCompare(b.type)),
        COMPLETE: (array) => array.sort((a, b) => a.isComplete - b.isComplete),
        TASKS: (array) => array.sort((a, b) => (a.nodes || []).length - (b.nodes || []).length),
      },
    },
  );

  function onSortChange(action, state) {
    console.log(action, state);
  }

  //* Drawer *//

  const [drawerId, setDrawerId] = React.useState(null);
  const [edited, setEdited] = React.useState('');

  const handleEdit = (event) => {
    setEdited(event.target.value);
  };

  const handleCancel = () => {
    setEdited('');
    setDrawerId(null);
  };

  const handleSave = () => {
    const node = findNodeById(data.nodes, drawerId);
    const editedNode = { ...node, name: edited };
    const nodes = insertNode(data.nodes, editedNode);

    setData({
      nodes,
    });

    setEdited('');
    setDrawerId(null);
  };

  //* Modal *//

  const [modalOpened, setModalOpened] = React.useState(false);

  //* Custom Modifiers *//

  let modifiedNodes = data.nodes;

  // search
  modifiedNodes = modifiedNodes.filter((node) =>
    node.name.toLowerCase().includes(search.toLowerCase()),
  );

  // filter
  modifiedNodes = isHide ? modifiedNodes.filter((node) => !node.isComplete) : modifiedNodes;

  //* Columns *//

  const COLUMNS = [
    {
      label: 'Task',
      renderCell: (item) => item.name,
      resize,
      sort: { sortKey: 'TASK' },
      select: {
        renderHeaderCellSelect: () => (
          <Checkbox
            colorScheme="teal"
            isChecked={select.state.all}
            isIndeterminate={!select.state.all && !select.state.none}
            onChange={select.fns.onToggleAll}
          />
        ),
        renderCellSelect: (item) => (
          <Checkbox
            colorScheme="teal"
            style={{ backgroundColor: '#ffffff' }}
            isChecked={select.state.ids.includes(item.id)}
            onChange={() => select.fns.onToggleById(item.id)}
          />
        ),
      },
      tree: true,
    },
    {
      label: 'Deadline',
      renderCell: (item) =>
        item.deadline.toLocaleDateString('en-US', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
        }),
      resize,
      sort: { sortKey: 'DEADLINE' },
    },
    { label: 'Type', renderCell: (item) => item.type, resize, sort: { sortKey: 'TYPE' } },
    {
      label: 'Complete',
      renderCell: (item) => item.isComplete.toString(),
      resize,
      sort: { sortKey: 'COMPLETE' },
    },
    {
      label: 'Tasks',
      renderCell: (item) => (
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span>{item.nodes?.length}</span>
          <IconButton
            aria-label="edit"
            icon={<FaPen />}
            size="xs"
            variant="ghost"
            colorScheme="teal"
            onClick={() => setDrawerId(item.id)}
          />
        </div>
      ),
      resize,
      sort: { sortKey: 'TASKS' },
    },
  ];

  return (
    <>
      <Modal isOpen={modalOpened} onClose={() => setModalOpened(false)}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>Not all features included here, but we got ...</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Resize
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Sort
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Search
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Filter
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Select
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Tree
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Drawer on Edit
              </Checkbox>
            </div>
            <div>
              <Checkbox colorScheme="teal" isChecked>
                Pagination
              </Checkbox>
            </div>
          </ModalBody>
        </ModalContent>
      </Modal>

      {/* Form */}

      <HStack m={3}>
        <Button colorScheme="teal" onClick={() => setModalOpened(true)}>
          Features?
        </Button>

        <InputGroup>
          <InputLeftElement
            pointerEvents="none"
            children={<FaSearch style={{ color: '#4a5568' }} />}
          />
          <Input
            placeholder="Search Task"
            value={search}
            onChange={(event) => setSearch(event.target.value)}
          />
        </InputGroup>

        <Checkbox
          style={{ whiteSpace: 'nowrap' }}
          colorScheme="teal"
          isChecked={isHide}
          onChange={(event) => setHide(event.target.checked)}
        >
          Hide Complete
        </Checkbox>
      </HStack>

      {/* Table */}

      <Box p={3} borderWidth="1px" borderRadius="lg">
        <CompactTable
          columns={COLUMNS}
          data={{ ...data, nodes: modifiedNodes }}
          theme={theme}
          layout={{ custom: true }}
          select={select}
          tree={tree}
          sort={sort}
          pagination={pagination}
        />
      </Box>

      <br />
      <HStack justify="flex-end">
        <IconButton
          aria-label="previous page"
          icon={<FaChevronLeft />}
          colorScheme="teal"
          variant="ghost"
          disabled={pagination.state.page === 0}
          onClick={() => pagination.fns.onSetPage(pagination.state.page - 1)}
        />

        {pagination.state.getPages(modifiedNodes).map((_, index) => (
          <Button
            key={index}
            colorScheme="teal"
            variant={pagination.state.page === index ? 'solid' : 'ghost'}
            onClick={() => pagination.fns.onSetPage(index)}
          >
            {index + 1}
          </Button>
        ))}
        <IconButton
          aria-label="next page"
          icon={<FaChevronRight />}
          colorScheme="teal"
          variant="ghost"
          disabled={pagination.state.page + 1 === pagination.state.getTotalPages(data.nodes)}
          onClick={() => pagination.fns.onSetPage(pagination.state.page + 1)}
        />
      </HStack>

      <Drawer isOpen={drawerId} onClose={handleCancel} placement="right">
        <DrawerOverlay />
        <DrawerContent>
          <DrawerCloseButton />
          <DrawerHeader>Create your account</DrawerHeader>

          <DrawerBody>
            <Text>Name: </Text>
            <Input
              autoFocus
              value={
                edited || fromTreeToList(data.nodes).find((node) => node.id === drawerId)?.name
              }
              onChange={handleEdit}
              data-autofocus
            />
          </DrawerBody>

          <DrawerFooter>
            <Button variant="outline" mr={3} onClick={handleCancel}>
              Cancel
            </Button>
            <Button onClick={handleSave} colorScheme="teal">
              Save
            </Button>
          </DrawerFooter>
        </DrawerContent>
      </Drawer>
    </>
  );
}
Example #25
Source File: ChallengeExpandedCard.jsx    From scaffold-directory with MIT License 4 votes vote down vote up
ChallengeExpandedCard = ({ challengeId, challenge, builderAttemptedChallenges }) => {
  const { borderColor, secondaryFontColor } = useCustomColorModes();

  const builderHasCompletedDependenciesChallenges = challenge.dependencies?.every(id => {
    if (!builderAttemptedChallenges[id]) {
      return false;
    }
    if (!(builderAttemptedChallenges[id].status === CHALLENGE_SUBMISSION_STATUS.ACCEPTED)) {
      return false;
    }
    if (challenge.lockedTimestamp) {
      return (
        new Date().getTime() - builderAttemptedChallenges[id].submittedTimestamp > challenge.lockedTimestamp * 60 * 1000
      );
    }

    return true;
  });

  const pendingDependenciesChallenges = challenge.dependencies?.filter(dependency => {
    return (
      !builderAttemptedChallenges[dependency] ||
      builderAttemptedChallenges[dependency].status !== CHALLENGE_SUBMISSION_STATUS.ACCEPTED
    );
  });

  const lockReasonToolTip = "The following challenges are not completed: " + pendingDependenciesChallenges.join(", ");

  const isRampUpChallenge = challenge.dependencies?.length === 0;
  const challengeStatus = builderAttemptedChallenges[challengeId]?.status;

  let colorScheme;
  let label;
  switch (challengeStatus) {
    case CHALLENGE_SUBMISSION_STATUS.ACCEPTED: {
      colorScheme = "green";
      label = "Accepted";
      break;
    }
    case CHALLENGE_SUBMISSION_STATUS.REJECTED: {
      colorScheme = "red";
      label = "Rejected";
      break;
    }
    case CHALLENGE_SUBMISSION_STATUS.SUBMITTED: {
      label = "Submitted";
      break;
    }
    default:
    // do nothing
  }

  const isChallengeLocked = challenge.disabled || !builderHasCompletedDependenciesChallenges;

  if (challenge.checkpoint) {
    return (
      <Box bg="#f9f9f9">
        <Flex maxW={500} overflow="hidden" m="0 auto 24px" opacity={isChallengeLocked ? "0.5" : "1"}>
          <Flex pt={6} pb={4} px={4} direction="column" grow={1}>
            <Flex alignItems="center" pb={4} direction="column">
              <Text fontWeight="bold" fontSize="lg" mb={2}>
                {challenge.label}
              </Text>
              <Center borderBottom="1px" borderColor={borderColor} w="200px" flexShrink={0} p={1}>
                <Image src={challenge.previewImage} objectFit="cover" />
              </Center>
            </Flex>
            <Text color={secondaryFontColor} mb={4} textAlign="center">
              {challenge.description}
            </Text>
            <Spacer />
            <ButtonGroup>
              <Button
                as={isChallengeLocked ? Button : Link}
                href={isChallengeLocked ? null : challenge.externalLink?.link}
                isDisabled={isChallengeLocked}
                variant={isChallengeLocked ? "outline" : "solid"}
                isFullWidth
                isExternal
              >
                {builderHasCompletedDependenciesChallenges ? (
                  <chakra.span>{challenge.externalLink.claim}</chakra.span>
                ) : (
                  <>
                    <span role="img" aria-label="lock icon">
                      ?
                    </span>
                    <chakra.span ml={1}>Locked</chakra.span>
                  </>
                )}
              </Button>
              {!builderHasCompletedDependenciesChallenges && (
                <Tooltip label={lockReasonToolTip}>
                  <IconButton icon={<QuestionOutlineIcon />} />
                </Tooltip>
              )}
            </ButtonGroup>
          </Flex>
        </Flex>
      </Box>
    );
  }

  return (
    <Flex maxW={880} borderWidth="1px" borderRadius="lg" borderColor={borderColor} overflow="hidden" mb={6}>
      <Center borderBottom="1px" borderColor={borderColor} w="200px" flexShrink={0} p={1}>
        {challenge.previewImage ? (
          <Image src={challenge.previewImage} objectFit="cover" />
        ) : (
          <Text p={3} textAlign="center">
            {challengeId} image
          </Text>
        )}
      </Center>
      <Flex pt={6} pb={4} px={4} direction="column" grow={1}>
        <Flex justify="space-between" pb={4}>
          <Text fontWeight="bold">{challenge.label}</Text>
          {isRampUpChallenge && challengeStatus && (
            <Badge borderRadius="xl" colorScheme={colorScheme} textTransform="none" py={0.5} px={2.5}>
              {label}
            </Badge>
          )}
        </Flex>
        <Text color={secondaryFontColor} mb={4}>
          {challenge.description}
        </Text>
        <Spacer />
        {challenge.externalLink?.link ? (
          // Redirect to externalLink if set (instead of challenge detail view)
          <ButtonGroup>
            <Button
              as={isChallengeLocked ? Button : Link}
              href={isChallengeLocked ? null : challenge.externalLink?.link}
              isDisabled={isChallengeLocked}
              variant={isChallengeLocked ? "outline" : "solid"}
              isFullWidth
              isExternal
            >
              {builderHasCompletedDependenciesChallenges ? (
                <chakra.span>{challenge.externalLink.claim}</chakra.span>
              ) : (
                <>
                  <span role="img" aria-label="lock icon">
                    ?
                  </span>
                  <chakra.span ml={1}>Locked</chakra.span>
                </>
              )}
            </Button>
            {!builderHasCompletedDependenciesChallenges && (
              <Tooltip label={lockReasonToolTip}>
                <IconButton icon={<QuestionOutlineIcon />} />
              </Tooltip>
            )}
          </ButtonGroup>
        ) : (
          <ButtonGroup>
            <Button
              as={RouteLink}
              to={!isChallengeLocked && `/challenge/${challengeId}`}
              isDisabled={isChallengeLocked}
              variant={isChallengeLocked ? "outline" : "solid"}
              isFullWidth
            >
              {!isChallengeLocked ? (
                <>
                  {" "}
                  <span role="img" aria-label="castle icon">
                    ⚔️
                  </span>
                  <chakra.span ml={1}>Quest</chakra.span>
                </>
              ) : (
                <>
                  <span role="img" aria-label="lock icon">
                    ?
                  </span>
                  <chakra.span ml={1}>Locked</chakra.span>
                </>
              )}
            </Button>
            {!builderHasCompletedDependenciesChallenges && (
              <Tooltip label={lockReasonToolTip}>
                <IconButton icon={<QuestionOutlineIcon />} />
              </Tooltip>
            )}
          </ButtonGroup>
        )}
      </Flex>
    </Flex>
  );
}
Example #26
Source File: components.js    From idena-web with MIT License 4 votes vote down vote up
export function ValidationReportSummary({onClose, ...props}) {
  const {t, i18n} = useTranslation()

  const {colors} = useTheme()
  const router = useRouter()

  const [{isValidated, status}] = useIdentity()

  const {
    lastValidationScore,
    totalScore,
    earnings,
    earningsScore,
    totalMissedReward,
    validationResult,
    isLoading,
    isFailed,
  } = useValidationReportSummary()

  const maybeNew =
    !status ||
    [
      IdentityStatus.Undefined,
      IdentityStatus.Invite,
      IdentityStatus.Candidate,
    ].includes(status)

  if (isFailed || (isLoading && maybeNew)) return null

  const {
    short: {score: shortScore},
  } = lastValidationScore

  const dna = toLocaleDna(i18n.language, {maximumFractionDigits: 3})

  const tweet = () =>
    openExternalUrl(`
  https://twitter.com/intent/tweet?text=${encodeURIComponent(
    `I've earned ${earnings.toLocaleString(i18n.language, {
      maximumFractionDigits: 3,
    })} $IDNA`
  )}&url=https://idena.io/join-idena&hashtags=Idena,ubi,blockchain,mining
`)

  return (
    <Box w="100%" pb={[2, 0]} {...props}>
      <Flex
        borderTop="4px solid"
        borderTopColor={
          // eslint-disable-next-line no-nested-ternary
          isLoading
            ? 'transparent'
            : // eslint-disable-next-line no-nested-ternary
            isValidated
            ? validationResult === ValidationResult.Penalty
              ? 'orange.500'
              : 'green.500'
            : 'red.500'
        }
        borderRadius="md"
        boxShadow="0 3px 12px 0 rgba(83, 86, 92, 0.1), 0 2px 3px 0 rgba(83, 86, 92, 0.2)"
        px={[7, 8]}
        pt={6}
        pb={[2, 6]}
        position="relative"
        w="100%"
      >
        <CloseButton
          w={6}
          h={6}
          pos="absolute"
          top={3}
          right={3}
          onClick={onClose}
        />
        <Stack spacing={6} w="full">
          <Skeleton isLoaded={!isLoading} alignSelf="start" w="auto">
            <Text fontSize="lg" fontWeight={500}>
              {(() => {
                switch (validationResult) {
                  case ValidationResult.Success:
                    return t('Successfully validated')
                  case ValidationResult.Penalty:
                    return t('Validated')
                  default:
                    return t('Validation failed')
                }
              })()}
            </Text>
          </Skeleton>
          <Stack spacing={[6, 10]}>
            <Flex justify="space-between" direction={['column', 'row']}>
              <ValidationReportGauge>
                <ValidationReportGaugeBox>
                  {isLoading ? (
                    <ValidationReportGaugeBar color={colors.gray['100']} />
                  ) : isValidated ? (
                    <ValidationReportGaugeBar
                      value={totalScore * 100}
                      color={
                        // eslint-disable-next-line no-nested-ternary
                        totalScore <= 0.75
                          ? colors.red[500]
                          : totalScore <= 0.9
                          ? colors.orange[500]
                          : colors.green[500]
                      }
                    />
                  ) : (
                    <ValidationReportGaugeBar
                      value={shortScore * 100 || 2}
                      color={colors.red[500]}
                    />
                  )}
                  <ValidationReportGaugeIcon
                    display={['none', 'initial']}
                    icon={<TimerIcon />}
                  />
                </ValidationReportGaugeBox>
                <ValidationReportGaugeStat>
                  <Skeleton isLoaded={!isLoading} w="auto">
                    {isValidated ? (
                      <ValidationReportGaugeStatValue>
                        {toPercent(totalScore)}
                      </ValidationReportGaugeStatValue>
                    ) : (
                      <ValidationReportGaugeStatValue color="red.500">
                        {t('Failed')}
                      </ValidationReportGaugeStatValue>
                    )}
                  </Skeleton>
                  <ValidationReportGaugeStatLabel>
                    {[
                      ValidationResult.Success,
                      ValidationResult.Penalty,
                    ].includes(validationResult) && t('Score')}
                    {validationResult === ValidationResult.LateSubmission &&
                      t('Late submission')}
                    {validationResult === ValidationResult.MissedValidation &&
                      t('Missed validation')}
                    {validationResult === ValidationResult.WrongAnswers &&
                      t('Wrong answers')}
                  </ValidationReportGaugeStatLabel>
                </ValidationReportGaugeStat>
              </ValidationReportGauge>
              <ValidationReportGauge mt={[6, 0]}>
                <ValidationReportGaugeBox>
                  {isLoading ? (
                    <ValidationReportGaugeBar color={colors.gray['100']} />
                  ) : isValidated ? (
                    <ValidationReportGaugeBar
                      value={earningsScore * 100 || 2}
                      color={
                        // eslint-disable-next-line no-nested-ternary
                        earningsScore <= 0.5
                          ? colors.red[500]
                          : earningsScore <= 0.75
                          ? colors.orange[500]
                          : colors.green[500]
                      }
                    />
                  ) : (
                    <ValidationReportGaugeBar
                      value={2}
                      color={colors.red[500]}
                    />
                  )}
                  <ValidationReportGaugeIcon
                    display={['none', 'initial']}
                    icon={<SendOutIcon />}
                  />
                </ValidationReportGaugeBox>
                <ValidationReportGaugeStat>
                  <Skeleton isLoaded={!isLoading} w="auto">
                    {validationResult === ValidationResult.Success ? (
                      <ValidationReportGaugeStatValue>
                        {dna(earnings)}
                      </ValidationReportGaugeStatValue>
                    ) : (
                      <ValidationReportGaugeStatValue color="red.500">
                        {dna(totalMissedReward)}
                      </ValidationReportGaugeStatValue>
                    )}
                  </Skeleton>
                  <ValidationReportGaugeStatLabel>
                    {t('Earnings')}
                  </ValidationReportGaugeStatLabel>
                </ValidationReportGaugeStat>
              </ValidationReportGauge>
            </Flex>
            <Flex display={['flex', 'none']} justify="space-around">
              <Button
                onClick={tweet}
                variant="primaryFlat"
                size="lg"
                fontWeight={500}
                isDisabled={!isValidated}
              >
                {t('Share')}
              </Button>
              <Divider
                display={['block', 'none']}
                h={10}
                orientation="vertical"
                color="gray.100"
              />
              <Button
                onClick={() => router.push('/validation-report')}
                variant="primaryFlat"
                size="lg"
                fontWeight={500}
              >
                {t('Details')}
              </Button>
            </Flex>
            <Flex
              display={['none', 'flex']}
              justify="space-between"
              alignItems="center"
            >
              <Box>
                <TextLink
                  href="/validation-report"
                  fontWeight={500}
                  display="inline-block"
                >
                  <Stack isInline spacing={0} align="center">
                    <Text as="span">{t('More details')}</Text>
                    <ChevronDownIcon boxSize={4} transform="rotate(-90deg)" />
                  </Stack>
                </TextLink>
              </Box>
              <Stack isInline color="muted">
                <IconButton
                  icon={<TwitterIcon boxSize={5} />}
                  size="xs"
                  variant="ghost"
                  color="blue.500"
                  fontSize={20}
                  _hover={{bg: 'blue.50'}}
                  onClick={tweet}
                />
              </Stack>
            </Flex>
          </Stack>
        </Stack>
      </Flex>
    </Box>
  )
}
Example #27
Source File: containers.js    From idena-web with MIT License 4 votes vote down vote up
export function VotingInspector({onTerminate, ...contract}) {
  const [result, setResult] = React.useState({})

  const {isOpen, onOpen, onClose} = useDisclosure()
  const {isOpen: isOpenContract, onToggle: onToggleContract} = useDisclosure()

  return (
    <>
      <Button
        bg="blue.50"
        rightIcon="info"
        variant="ghost"
        colorScheme="blue"
        onClick={onOpen}
      >
        Open inspector
      </Button>
      <ChakraDrawer isOpen={isOpen} size="lg" onClose={onClose}>
        <DrawerOverlay bg="xblack.080" />
        <DrawerContent px={8} py={12} overflowY="auto">
          <DrawerCloseButton />
          <DrawerHeader>
            <Heading fontSize="lg" fontWeight={500} mb={2}>
              Inspector
            </Heading>
          </DrawerHeader>
          <DrawerBody fontSize="md">
            <Stack spacing={4} w="lg">
              <Stack>
                <Flex align="center">
                  <Heading fontSize="base" fontWeight={500} my={4}>
                    Contract
                  </Heading>
                  <IconButton
                    icon="chevron-down"
                    size="sm"
                    fontSize="lg"
                    ml={1}
                    onClick={onToggleContract}
                  />
                </Flex>
                <Collapse isOpen={isOpenContract}>
                  <Debug>{contract}</Debug>
                </Collapse>
                <Box mt={2}>
                  <Heading fontSize="base" fontWeight={500} my={4}>
                    readonlyCall
                  </Heading>
                  <Stack
                    as="form"
                    spacing={3}
                    onSubmit={async e => {
                      e.preventDefault()
                      const {
                        readonlyCallMethod,
                        readonlyCallMethodFormat,
                        readonlyCallArgs,
                      } = e.target.elements

                      setResult(
                        await createContractReadonlyCaller(contract)(
                          readonlyCallMethod.value,
                          readonlyCallMethodFormat.value,
                          JSON.parse(readonlyCallArgs.value || '[]')
                        )
                      )
                    }}
                  >
                    <Stack isInline spacing={2} justify="space-between">
                      <Input
                        id="readonlyCallMethod"
                        placeholder="readonlyCallMethod method"
                      />
                      <Input
                        id="readonlyCallMethodFormat"
                        placeholder="format"
                        w={100}
                      />
                    </Stack>
                    <Input
                      id="readonlyCallArgs"
                      placeholder="readonlyCall args"
                    />
                    <SecondaryButton type="submit" ml="auto">
                      Readonly call
                    </SecondaryButton>
                  </Stack>
                </Box>
                <Box>
                  <Heading fontSize="base" fontWeight={500} my={4}>
                    readKey
                  </Heading>
                  <Stack
                    as="form"
                    spacing={3}
                    onSubmit={async e => {
                      e.preventDefault()

                      const {readKey, readKeyFormat} = e.target.elements

                      setResult(
                        await createContractDataReader(contract.contractHash)(
                          readKey.value,
                          readKeyFormat.value
                        )
                      )
                    }}
                  >
                    <Stack isInline>
                      <Input id="readKey" placeholder="readKey key" />
                      <Input id="readKeyFormat" placeholder="format" w={100} />
                    </Stack>
                    <SecondaryButton
                      type="submit"
                      ml="auto"
                      onClick={async () => {}}
                    >
                      Read data
                    </SecondaryButton>
                  </Stack>
                </Box>
                <Box>
                  <Heading fontSize="base" fontWeight={500} my={4}>
                    txReceipt
                  </Heading>
                  <Stack
                    as="form"
                    spacing={3}
                    onSubmit={async e => {
                      e.preventDefault()
                      setResult(
                        await callRpc(
                          'bcn_txReceipt',
                          e.target.elements.txHash.value
                        )
                      )
                    }}
                  >
                    <Stack isInline>
                      <Input id="txHash" placeholder="txHash" />
                    </Stack>
                    <SecondaryButton
                      type="submit"
                      ml="auto"
                      onClick={async () => {}}
                    >
                      Show receipt
                    </SecondaryButton>
                  </Stack>
                </Box>
                <Box>
                  <Heading fontSize="base" fontWeight={500} my={4}>
                    contract_getStake
                  </Heading>
                  <Stack
                    as="form"
                    spacing={3}
                    onSubmit={async e => {
                      e.preventDefault()
                      setResult(
                        await callRpc(
                          'contract_getStake',
                          contract.contractHash
                        )
                      )
                    }}
                  >
                    <Stack isInline>
                      <Input
                        value={contract.contractHash}
                        isReadonly
                        isDisabled
                      />
                    </Stack>
                    <SecondaryButton
                      type="submit"
                      ml="auto"
                      onClick={async () => {}}
                    >
                      Get stake
                    </SecondaryButton>
                  </Stack>
                </Box>
                <Box ml="auto" mt={6}>
                  <PrimaryButton
                    colorScheme="red"
                    variant="solid"
                    _active={{}}
                    onClick={onTerminate}
                  >
                    Terminate contact
                  </PrimaryButton>
                </Box>
              </Stack>
              <Debug>{result}</Debug>
            </Stack>
          </DrawerBody>
        </DrawerContent>
      </ChakraDrawer>
    </>
  )
}
Example #28
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 #29
Source File: Footer.js    From benjamincarlson.io with MIT License 4 votes vote down vote up
Footer = () => {

    const { colorMode } = useColorMode()
    const borderIcon = {
        light: 'gray.400',
        dark: 'gray.500'
    }
    const footerHoverBg = {
        light: 'gray.100',
        dark: 'gray.700',
    }
    return (
        <Box bgColor={useColorModeValue("rgb(248, 250, 252)", "gray.900")} mt={4}>
            <Flex
                align="center"
                my={4}
                direction="column"
            >
                <div>
                    <Link href="https://twitter.com/bjmncrlsn" title="Twitter" isExternal>
                        <IconButton
                            aria-label="Twitter"
                            icon={<FiTwitter />}
                            size="lg"
                            color={borderIcon[colorMode]}
                            variant="ghost"
                            _hover={{ backgroundColor: footerHoverBg[colorMode] }}
                        />
                    </Link>
                    <Link href="https://github.com/bjcarlson42" title="GitHub" isExternal>
                        <IconButton
                            aria-label="GitHub"
                            icon={<FiGithub />}
                            size="lg"
                            color={borderIcon[colorMode]}
                            variant="ghost"
                            _hover={{ backgroundColor: footerHoverBg[colorMode] }}
                        />
                    </Link>
                    <Link
                        href="https://www.linkedin.com/in/bjcarlson42"
                        title="LinkedIn"
                        isExternal
                    >
                        <IconButton
                            aria-label="LinkedIn"
                            icon={<FiLinkedin />}
                            size="lg"
                            color={borderIcon[colorMode]}
                            variant="ghost"
                            _hover={{ backgroundColor: footerHoverBg[colorMode] }}
                        />
                    </Link>
                    <Link
                        href="https://www.youtube.com/benjamincarlson"
                        title="YouTube"
                        isExternal
                    >
                        <IconButton
                            aria-label="YouTube"
                            icon={<FiYoutube />}
                            size="lg"
                            color={borderIcon[colorMode]}
                            variant="ghost"
                            _hover={{ backgroundColor: footerHoverBg[colorMode] }}
                        />
                    </Link>
                    <Link href="mailto:[email protected]" title="Email" isExternal>
                        <IconButton
                            aria-label="Email"
                            icon={<FiMail />}
                            size="lg"
                            color={borderIcon[colorMode]}
                            variant="ghost"
                            _hover={{ backgroundColor: footerHoverBg[colorMode] }}
                        />
                    </Link>
                </div>
            </Flex>
        </Box>
    )
}