@chakra-ui/react#Center JavaScript Examples
The following examples show how to use
@chakra-ui/react#Center.
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: BuilderListSkeleton.jsx From scaffold-directory with MIT License | 6 votes |
BuilderListSkeleton = () => (
<Box overflowX="auto">
<Center mb={5}>
<chakra.strong mr={2}>Total builders:</chakra.strong> <SkeletonText noOfLines={1} w={5} />
</Center>
<Table>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Challenges</Th>
<Th>Socials</Th>
<Th>Last Activity</Th>
</Tr>
</Thead>
<Tbody>
{[1, 2].map(lineNumber => {
return (
<Tr key={lineNumber}>
<Td>
<SkeletonAddress w="12.5" fontSize="16" />
</Td>
<Td>
<SkeletonText noOfLines={1} py={2} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={2} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={2} />
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
)
Example #2
Source File: saved-blobs.js From blobs.app with MIT License | 6 votes |
SecondPage = () => (
<Layout>
<SEO
title="Save blobs locally and access them anytime even when in offline"
description="Customizable blobs as SVG and Flutter Widget. Create random or fixed blobs, loop, animate, clip them with ease"
/>
<Box my="10" textAlign="center">
<Logo />
<Heading
size="xl"
display="flex"
alignItems="center"
justifyContent="center"
variant="main"
>
Browse saved blobs
</Heading>
<Text my="2" variant="subtle">
Click on the any blob card to navigate to edit screen
</Text>
</Box>
<SavedBlobs />
<Center>
<Link to="/">
{' '}
<ArrowBackIcon />
Go back to the homepage
</Link>
</Center>
</Layout>
)
Example #3
Source File: UrlInput.js From blobs.app with MIT License | 6 votes |
UrlInput = ({ value, onEnter }) => {
const [error, setError] = useState(null);
const urlRegex = /([\w+]+\:\/\/)?([\w\d-]+\.)*[\w-]+[\.\:]\w+([\/\?\=\&\#\.]?[\w-]+)*\/?/gm;
return (
<Box key={value}>
<ChakInput
variant="outline"
placeholder="https://someurl.png"
bg="white"
_dark={{ bg: 'gray.600' }}
defaultValue={value}
_focus={{ borderColor: 'primary', boxShadow: '0 0 0 1px #d7819b' }}
onKeyDown={(e) => {
if (e.key !== 'Enter') return;
const url = e.target.value;
if (!urlRegex.test(url)) {
setError('Invalid URL');
return;
}
setError(null);
onEnter(url);
}}
/>
{error && (
<Center>
<Text mt="2" fontSize="sm" color="red.600" fontWeight="600">
{error}
</Text>
</Center>
)}
</Box>
);
}
Example #4
Source File: components.js From idena-web with MIT License | 6 votes |
export function DrawerPromotion(props) {
const [, setDrawerPromotion] = React.useContext(DrawerPromotionContext)
return (
<Center
ref={setDrawerPromotion}
position="absolute"
top="50%"
left="50%"
transform="translate(-50%,-50%)"
zIndex="modal"
{...props}
/>
)
}
Example #5
Source File: components.js From idena-web with MIT License | 6 votes |
export function EmptyAdList({children}) {
const {t} = useTranslation()
return (
<Center color="muted" flex={1} w="full">
<Stack spacing="4" align="center">
<Text>{children}</Text>
<NextLink href="/adn/new">
<Button variant="outline">{t('Create a new ad')}</Button>
</NextLink>
</Stack>
</Center>
)
}
Example #6
Source File: offers.js From idena-web with MIT License | 5 votes |
export default function AdOfferList() {
const {t} = useTranslation()
const queryClient = useQueryClient()
const {data: burntCoins, status: burntCoinsStatus} = useApprovedBurntCoins()
const isFetched = burntCoinsStatus === 'success'
const isEmpty = isFetched && burntCoins.length === 0
const [selectedAd, setSelectedAd] = React.useState({})
const burnDisclosure = useDisclosure()
const {
onOpen: onOpenBurnDisclosure,
onClose: onCloseBurnDisclosure,
} = burnDisclosure
const handlePreviewBurn = React.useCallback(
ad => {
setSelectedAd(ad)
onOpenBurnDisclosure()
},
[onOpenBurnDisclosure]
)
const handleBurn = React.useCallback(() => {
onCloseBurnDisclosure()
queryClient.invalidateQueries(['bcn_burntCoins', []])
}, [onCloseBurnDisclosure, queryClient])
return (
<Layout skipBanner>
<Page>
<PageHeader>
<PageTitle mb={4}>{t('All offers')}</PageTitle>
<PageCloseButton href="/adn/list" />
</PageHeader>
<Table>
<Thead>
<Tr>
<RoundedTh isLeft>{t('Banner/author')}</RoundedTh>
<RoundedTh>{t('Website')}</RoundedTh>
<RoundedTh>{t('Target')}</RoundedTh>
<RoundedTh>{t('Burn')}</RoundedTh>
<RoundedTh isRight />
</Tr>
</Thead>
<Tbody>
{isFetched &&
burntCoins.map(burn => (
<AdOfferListItem
key={burn.key}
burn={burn}
onBurn={handlePreviewBurn}
/>
))}
</Tbody>
</Table>
{isEmpty && (
<Center color="muted" mt="4" w="full">
{t('No active offers')}
</Center>
)}
<BurnDrawer ad={selectedAd} onBurn={handleBurn} {...burnDisclosure} />
</Page>
</Layout>
)
}
Example #7
Source File: containers.js From idena-web with MIT License | 5 votes |
export function AdMediaInput({
name,
value,
label,
description,
fallbackSrc,
maybeError,
onChange,
...props
}) {
const src = React.useMemo(
() =>
isValidImage(value) ? URL.createObjectURL(value) : value ?? adFallbackSrc,
[value]
)
return (
<FormControl isInvalid={Boolean(maybeError)}>
<FormLabel htmlFor={name} m={0} p={0}>
<VisuallyHiddenInput
id={name}
name={name}
type="file"
accept="image/png,image/jpg,image/jpeg"
onChange={async e => {
if (onChange) {
const {files} = e.target
if (files.length) {
const [file] = files
if (hasImageType(file)) {
onChange(file)
}
}
}
}}
{...props}
/>
<HStack spacing={4} align="center" cursor="pointer">
<Box flexShrink={0}>
{src !== adFallbackSrc ? (
<AdImage src={src} width={70} />
) : (
<Center
bg="gray.50"
borderWidth={1}
borderColor="gray.016"
rounded="lg"
p="3"
>
<Image src={fallbackSrc} ignoreFallback boxSize="44px" />
</Center>
)}
</Box>
<Stack>
<HStack>
<LaptopIcon boxSize="5" color="blue.500" />
<Text color="blue.500" fontWeight={500}>
{label}
</Text>
</HStack>
<SmallText>{description}</SmallText>
</Stack>
</HStack>
<AdFormError>{maybeError}</AdFormError>
</FormLabel>
</FormControl>
)
}
Example #8
Source File: components.js From idena-web with MIT License | 5 votes |
export function PublishFlipDrawer({isPending, flip, onSubmit, ...props}) {
const {t} = useTranslation()
return (
<AdDrawer isMining={isPending} {...props}>
<DrawerHeader>
<Stack spacing={4}>
<Center
alignSelf="flex-start"
bg="blue.012"
w={12}
minH={12}
rounded="xl"
>
<PublishFlipIcon boxSize={6} color="blue.500" />
</Center>
<Heading color="gray.500" fontSize="lg" fontWeight={500}>
{t('Submit flip')}
</Heading>
</Stack>
</DrawerHeader>
<DrawerBody overflowY="auto" mx={-6} mt="3" mb={10}>
<Stack spacing={6} fontSize="md" px={6} align="center">
<HStack spacing="3">
<FlipImageList>
{flip.originalOrder.map((num, idx) => (
<FlipImageListItem
key={num}
src={flip?.images[num]}
isFirst={idx === 0}
isLast={idx === flip?.images.length - 1}
w="24"
/>
))}
</FlipImageList>
<FlipImageList>
{flip.order.map((num, idx) => (
<FlipImageListItem
key={num}
src={flip?.images[num]}
isFirst={idx === 0}
isLast={idx === flip?.images.length - 1}
w="24"
/>
))}
</FlipImageList>
</HStack>
<FlipKeywordPanel w="full">
<Stack spacing="4">
{flip.keywords.map(word => (
<FlipKeyword key={word.id}>
<FlipKeywordName>{word.name}</FlipKeywordName>
<FlipKeywordDescription>{word.desc}</FlipKeywordDescription>
</FlipKeyword>
))}
</Stack>
</FlipKeywordPanel>
</Stack>
</DrawerBody>
<DrawerFooter>
<HStack>
{/* eslint-disable-next-line react/destructuring-assignment */}
<SecondaryButton onClick={props.onClose}>
{t('Not now')}
</SecondaryButton>
<PrimaryButton
isLoading={isPending}
loadingText={t('Mining...')}
onClick={onSubmit}
>
{t('Submit')}
</PrimaryButton>
</HStack>
</DrawerFooter>
</AdDrawer>
)
}
Example #9
Source File: components.js From idena-web with MIT License | 5 votes |
export function SpoilInviteDrawer({onSuccess, onFail, ...props}) {
const {t} = useTranslation()
return (
<Drawer {...props}>
<DrawerHeader mb={0}>
<Center flexDirection="column">
<Avatar address={dummyAddress} />
<Heading
fontSize="lg"
fontWeight={500}
color="gray.500"
mt="4"
mb={0}
>
{t('Spoil invitation code')}
</Heading>
</Center>
</DrawerHeader>
<DrawerBody mt="6">
<Text fontSize="md" mb={6}>
{t(
`Spoil invitations that are shared publicly. This will encourage people to share invitations privately and prevent bots from collecting invitation codes.`
)}
</Text>
<Stack spacing="6">
<form
id="spoilInvite"
onSubmit={async e => {
e.preventDefault()
const code = new FormData(e.target).get('code').trim()
const randomPrivateKey = generatePrivateKey()
try {
const hash = await sendRawTx(
new Transaction()
.fromHex(
await getRawTx(
TxType.ActivationTx,
privateKeyToAddress(code),
privateKeyToAddress(randomPrivateKey),
0,
0,
privateKeyToPublicKey(randomPrivateKey)
)
)
.sign(code)
.toHex(true)
)
// eslint-disable-next-line no-unused-expressions
onSuccess?.(hash)
} catch (error) {
// eslint-disable-next-line no-unused-expressions
onFail?.(error)
}
}}
>
<FormControl>
<FormLabel>{t('Invitation code')}</FormLabel>
<Input name="code" placeholder={t('Invitation code to spoil')} />
</FormControl>
</form>
<Text fontSize="md">
{t(
`When you click 'Spoil' the invitation code will be activated by a random address and wasted.`
)}
</Text>
</Stack>
</DrawerBody>
<DrawerFooter>
<PrimaryButton type="submit" form="spoilInvite">
{t('Spoil invite')}
</PrimaryButton>
</DrawerFooter>
</Drawer>
)
}
Example #10
Source File: ProductDetails.js From react-sample-projects with MIT License | 5 votes |
ProductDetails = () => {
const { product } = useSelector(state => state.product);
const dispatch = useDispatch();
const { state } = useLocation() || {};
const params = useParams();
const addItemToCartHandler = e => {
e.stopPropagation();
e.preventDefault();
dispatch(addItemToCart(product));
};
useEffect(() => {
if (!params.id) return;
if (state?.item) {
dispatch(setProductDetails(state?.item));
} else {
dispatch(fetchProductDetails(params.id));
}
return () => {};
}, [params.id, dispatch, state?.item]);
if (!product) return <Box m="3">loading...</Box>;
return (
<Box
m="3"
boxShadow="base"
borderWidth="1px"
borderRadius="lg"
overflow="hidden"
>
<SimpleGrid columns={{ sm: 1, md: 2, lg: 2 }} spacing="40px">
<Center>
<Box p="6">
<Image src={product.image} alt={product.title} maxH="400" />
</Box>
</Center>
<Box p="6">
<Box d="flex" alignItems="baseline">
<Box
color="gray.500"
fontWeight="semibold"
letterSpacing="wide"
fontSize="xs"
textTransform="uppercase"
>
{product.category}
</Box>
</Box>
<Box textAlign="left">${product.price}</Box>
<Box fontWeight="semibold" mt="1" as="h2" textAlign="left">
Product Info:
</Box>
<Box textAlign="left" fontSize="md">
{product.description}
</Box>
<Button
onClick={addItemToCartHandler}
m={3}
variant={'solid'}
colorScheme={'teal'}
size={'sm'}
>
Add to Cart
</Button>
</Box>
</SimpleGrid>
</Box>
);
}
Example #11
Source File: Item.js From react-sample-projects with MIT License | 5 votes |
Item = ({ item }) => {
const dispatch = useDispatch();
const addItemToCartHandler = e => {
e.stopPropagation();
e.preventDefault();
dispatch(addItemToCart(item));
};
return (
<Link to={{ pathname: `/product/${item.id}`, state: { item } }}>
<Box
boxShadow="base"
maxW="sm"
borderWidth="1px"
borderRadius="lg"
overflow="hidden"
>
<Box p="6">
<Center>
<Image
_hover={{ transform: `scale(1.1)` }}
src={item.image}
alt={item.title}
maxH="400"
height="400"
/>
</Center>
</Box>
<Box p="6">
<Box d="flex" alignItems="baseline">
<Box
color="gray.500"
fontWeight="semibold"
letterSpacing="wide"
fontSize="xs"
textTransform="uppercase"
>
{item.category}
</Box>
</Box>
<Box
mt="1"
fontWeight="semibold"
as="h4"
lineHeight="tight"
isTruncated
whiteSpace="wrap"
textAlign="left"
>
{item.title}
</Box>
<Flex justifyContent="space-between">
<Box textAlign="left">${item.price}</Box>
<Tooltip label="Add to Cart" fontSize="md">
<Button variant="ghost" p={2} onClick={addItemToCartHandler}>
<Icon as={MdShoppingCart} w={6} h={6} />
</Button>
</Tooltip>
</Flex>
</Box>
</Box>
</Link>
);
}
Example #12
Source File: Footer.js From blobs.app with MIT License | 5 votes |
Footer = ({ toggleSound, playSound }) => (
<Center my="6">
<HStack
spacing="10px"
fontSize="sm"
flexDirection={{ base: 'column-reverse', lg: 'row' }}
>
<Button
variant="silent"
leftIcon={<CopyrightIcon fontSize="lg" />}
aria-label="Toggle Theme"
>
Copyright 2021
</Button>
<Modal
title="Source code & Libraries"
size="md"
src={
<Button
variant="silent"
leftIcon={<GithubIcon fontSize="lg" />}
aria-label="Source code"
>
Source code
</Button>
}
>
<Box>
<SourceCode />
</Box>
</Modal>
<Modal
title="Credits"
size="md"
src={
<Button
variant="silent"
leftIcon={<CreditsIcon fontSize="lg" />}
aria-label="Credits"
>
Credits
</Button>
}
>
<Box>
<Credits />
</Box>
</Modal>
<LoIcon />
<Button
variant="silent"
leftIcon={<UserIcon fontSize="lg" />}
aria-label="Lokesh Rajendran"
target="_blank"
as={Link}
href="https://twitter.com/lokesh_coder"
>
lokesh_coder
</Button>
<Button
variant="silent"
leftIcon={(() => {
if (!playSound) return <SoundOffIcon fontSize="lg" />;
return <SoundIcon fontSize="lg" />;
})()}
aria-label="Toggle Theme"
onClick={toggleSound}
>
Toggle sound
</Button>
<Box as={Text}>
<ThemeSwitch />
</Box>
</HStack>
</Center>
)
Example #13
Source File: NavLinks.js From blobs.app with MIT License | 5 votes |
NavLinks = ({ saveBlob }) => {
const toast = useToast();
return (
<Box px="10" pt="3">
<Center>
<HStack spacing="2px" fontSize="sm">
<Box as={Text}>
<Button
variant="heavy"
leftIcon={<BookmarkIcon fontSize="18px" />}
aria-label="Save blob"
onClick={() => {
saveBlob();
toast({
render: () => (
<Box
bg="primary"
my="10"
py="3"
px="5"
rounded="lg"
color="white"
textAlign="center"
fontWeight="500"
shadow="xl"
>
Blob Saved!
</Box>
),
duration: 2000,
});
}}
>
Save
</Button>
</Box>
<Box as={Text}>
<Button
href="/saved-blobs/"
as={GatbsyLink}
to="/saved-blobs"
variant="heavy"
leftIcon={<SavedIcon fontSize="18px" />}
aria-label="Saved blobs"
>
Saved blobs
</Button>
</Box>
<Box as={Text}>
<Button
href="http://www.twitter.com/intent/tweet?url=https://lokesh-coder.github.io/blobs.app/&text=Generate%20beautiful%20blob%20shapes%20for%20web%20and%20flutter%20apps"
target="_blank"
as={Link}
variant="heavy"
leftIcon={<TwitterIcon fontSize="18px" />}
aria-label="Share"
>
Share
</Button>
</Box>
</HStack>
</Center>
</Box>
);
}
Example #14
Source File: BuilderListView.jsx From scaffold-directory with MIT License | 4 votes |
export default function BuilderListView({ serverUrl, mainnetProvider, userRole }) {
const [builders, setBuilders] = useState([]);
const [isLoadingBuilders, setIsLoadingBuilders] = useState(false);
const { secondaryFontColor } = useCustomColorModes();
const isAdmin = userRole === USER_ROLES.admin;
const columns = useMemo(
() => [
{
Header: "Builder",
accessor: "builder",
disableSortBy: true,
Cell: ({ value }) => <BuilderAddressCell builderId={value} mainnetProvider={mainnetProvider} />,
},
{
Header: "Challenges",
accessor: "challenges",
sortDescFirst: true,
},
{
Header: "Socials",
accessor: "socials",
disableSortBy: true,
Cell: ({ value }) => <BuilderSocialLinksCell builder={value} isAdmin={isAdmin} />,
},
{
Header: "Last Activity",
accessor: "lastActivity",
sortDescFirst: true,
Cell: ({ value }) => <DateWithTooltip timestamp={value} />,
},
],
// eslint-disable-next-line
[userRole],
);
useEffect(() => {
async function fetchBuilders() {
setIsLoadingBuilders(true);
const fetchedBuilders = await axios.get(serverUrl + serverPath);
const processedBuilders = fetchedBuilders.data.map(builder => ({
builder: builder.id,
challenges: getAcceptedChallenges(builder?.challenges)?.length ?? 0,
socials: builder,
lastActivity: builderLastActivity(builder),
}));
setBuilders(processedBuilders);
setIsLoadingBuilders(false);
}
fetchBuilders();
}, [serverUrl]);
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data: builders,
initialState: { pageIndex: 0, pageSize: 25, sortBy: useMemo(() => [{ id: "lastActivity", desc: true }], []) },
},
useSortBy,
usePagination,
);
return (
<Container maxW="container.lg">
<Container maxW="container.md" centerContent>
<Heading as="h1" mb="4">
All Builders
</Heading>
<Text color={secondaryFontColor} textAlign="center" mb="10">
List of Ethereum builders creating products, prototypes, and tutorials with{" "}
<Link href="https://github.com/scaffold-eth/scaffold-eth" color="teal.500" isExternal>
scaffold-eth
</Link>
.
</Text>
</Container>
{isLoadingBuilders ? (
<BuilderListSkeleton />
) : (
<Box overflowX="auto" mb={8}>
<Center mb={5}>
<chakra.strong mr={2}>Total builders:</chakra.strong> {builders.length}
</Center>
<Table {...getTableProps()}>
<Thead>
{headerGroups.map(headerGroup => (
<Tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<Th {...column.getHeaderProps(column.getSortByToggleProps())}>
{column.render("Header")}
<chakra.span pl="4">
{column.isSorted ? (
column.isSortedDesc ? (
<TriangleDownIcon aria-label="sorted descending" />
) : (
<TriangleUpIcon aria-label="sorted ascending" />
)
) : null}
</chakra.span>
</Th>
))}
</Tr>
))}
</Thead>
<Tbody {...getTableBodyProps()}>
{page.map(row => {
prepareRow(row);
return (
<Tr {...row.getRowProps()}>
{row.cells.map(cell => (
<Td {...cell.getCellProps()}>{cell.render("Cell")}</Td>
))}
</Tr>
);
})}
</Tbody>
</Table>
<Center mt={4}>
<ButtonGroup>
<Button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
{"<<"}
</Button>
<Button onClick={() => previousPage()} disabled={!canPreviousPage}>
{"<"}
</Button>
<Button onClick={() => nextPage()} disabled={!canNextPage}>
{">"}
</Button>
<Button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
{">>"}
</Button>
</ButtonGroup>
</Center>
<Center mt={4}>
<Text mr={4}>
Page{" "}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{" "}
</Text>
<Box>
<Select
isFullWidth={false}
value={pageSize}
onChange={e => {
setPageSize(Number(e.target.value));
}}
>
{[25, 50, 100].map(pageSizeOption => (
<option key={pageSizeOption} value={pageSizeOption}>
Show {pageSizeOption}
</option>
))}
</Select>
</Box>
</Center>
</Box>
)}
</Container>
);
}
Example #15
Source File: components.js From idena-web with MIT License | 4 votes |
export function AdCarousel() {
const {t} = useTranslation()
const {lng} = useLanguage()
const {ads, currentIndex, setCurrentIndex, prev, next} = useRotateAds()
const currentAd = ads[currentIndex]
const {data: burntCoins} = useBurntCoins()
const orderedBurntCoins =
burntCoins
?.sort((a, b) => b.amount - a.amount)
.map(burn => ({...burn, ...AdBurnKey.fromHex(burn?.key)})) ?? []
const maybeBurn = orderedBurntCoins.find(burn => burn.cid === currentAd?.cid)
const formatDna = useFormatDna()
const swipeProps = useSwipeable({
onSwipedLeft: next,
onSwipedRight: prev,
preventDefaultTouchmoveEvent: true,
trackMouse: true,
})
return (
<Stack>
<Box
bg="white"
borderRadius="lg"
boxShadow="0 3px 12px 0 rgba(83, 86, 92, 0.1), 0 2px 3px 0 rgba(83, 86, 92, 0.2)"
pt="6"
px="28px"
pb="4"
{...swipeProps}
>
<Heading as="h3" fontSize="lg" fontWeight={500} isTruncated>
{currentAd?.title}
</Heading>
<Text color="muted" fontSize="mdx" mt="2">
{currentAd?.desc}
</Text>
<Box mt="3">
<ExternalLink
href={currentAd?.url}
fontSize="base"
fontWeight={500}
justifyContent="start"
maxW="64"
>
{currentAd?.url}
</ExternalLink>
</Box>
<LinkBox mt="5">
<LinkOverlay href={currentAd?.url} isExternal>
<AdImage src={currentAd?.media} w="full" />
</LinkOverlay>
</LinkBox>
<Stack spacing="1" mt="4" fontSize="base" divider={<HDivider />}>
<Stack spacing="1" pt="2" pb="2.5">
<Text fontWeight={500}>{t('Sponsored by')}</Text>
<HStack spacing="1" align="center">
<Avatar
address={currentAd?.author}
boxSize="6"
borderRadius="lg"
/>
<Text as="span" color="muted" isTruncated lineHeight="22px">
{currentAd?.author}
</Text>
</HStack>
</Stack>
<Stack spacing="1" pt="2" pb="2.5">
<Text fontWeight={500}>
{t('Burnt, {{time}}', {
time: new Intl.RelativeTimeFormat(lng, {
style: 'short',
}).format(24, 'hour'),
})}
</Text>
<Text color="muted">{formatDna(maybeBurn?.amount ?? 0)}</Text>
</Stack>
</Stack>
</Box>
<Center as={HStack} spacing="0.5" h="6">
{ads.map((_, idx) => (
<Box
w="6"
h="0.5"
bg={idx === currentIndex ? 'gray.500' : 'gray.030'}
borderRadius={1}
onClick={() => {
setCurrentIndex(idx)
}}
/>
))}
</Center>
<Box>
<SuccessAlert
icon={<InfoIcon color="green.500" boxSize={5} mr={3} />}
fontSize="md"
>
{t('Watching ads makes your coin valuable!')}
</SuccessAlert>
</Box>
</Stack>
)
}
Example #16
Source File: ChallengeExpandedCard.jsx From scaffold-directory with MIT License | 4 votes |
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 #17
Source File: BuilderProfileCard.jsx From scaffold-directory with MIT License | 4 votes |
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 #18
Source File: Targets.js From web-client with Apache License 2.0 | 4 votes |
ProjectTargets = ({ project }) => {
const query = useQuery();
const urlPageNumber = query.get('page') !== null ? parseInt(query.get('page')) : 1;
const [pageNumber, setPageNumber] = useState(urlPageNumber);
const [numberPages, setNumberPages] = useState(1);
const [targets, setTargets] = useState([]);
const { isOpen: isAddTargetDialogOpen, onOpen: openAddTargetDialog, onClose: closeAddTargetDialog } = useDisclosure();
const onDeleteButtonClick = (ev, targetId) => {
ev.preventDefault();
secureApiFetch(`/targets/${targetId}`, { method: 'DELETE' })
.then(() => {
reloadTargets();
})
}
const onTargetFormSaved = () => {
reloadTargets();
closeAddTargetDialog();
}
const reloadTargets = useCallback(() => {
setTargets([]);
secureApiFetch(`/targets?projectId=${project.id}&page=${pageNumber - 1}`, { method: 'GET' })
.then(resp => {
if (resp.headers.has('X-Page-Count')) {
setNumberPages(resp.headers.get('X-Page-Count'))
}
return resp.json()
})
.then(data => {
setTargets(data);
});
}, [pageNumber, project]);
const onPrevPageClick = () => {
setPageNumber(pageNumber - 1);
}
const onNextPageClick = () => {
setPageNumber(pageNumber + 1);
}
useEffect(() => {
reloadTargets()
}, [reloadTargets])
return <section>
<h4>
<IconServer />Targets
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<ButtonGroup>
<TargetModalDialog project={project} isOpen={isAddTargetDialogOpen} onSubmit={onTargetFormSaved} onCancel={closeAddTargetDialog} />
<CreateButton onClick={openAddTargetDialog}>Add target...</CreateButton>
</ButtonGroup>
</RestrictedComponent>
</h4>
{!targets ? <Loading /> :
<>
{numberPages > 1 && <Center>
<Pagination page={pageNumber - 1} total={numberPages} handlePrev={onPrevPageClick} handleNext={onNextPageClick} />
</Center>}
<Table>
<Thead>
<Tr>
<Th>Name</Th>
<Th>Sub-target</Th>
<Th>Kind</Th>
<Th>Vulnerable?</Th>
<Th> </Th>
</Tr>
</Thead>
<Tbody>
{targets.length === 0 && <NoResultsTableRow numColumns={4} />}
{targets.map((target, index) =>
<Tr key={index}>
<Td>
{target.parent_id === null &&
<HStack>
<Link to={`/targets/${target.id}`}><TargetBadge name={target.name} /></Link>
</HStack>
}
{target.parent_id !== null &&
<>{target.parent_name ?? '-'}</>
}
</Td>
<Td>{target.parent_id !== null ?
<>
<Link to={`/targets/${target.id}`}><TargetBadge name={target.name} /></Link>
</> : '-'}</Td>
<Td>{target.kind} <Tags values={target.tags} /></Td>
<Td>{target.num_vulnerabilities > 0 ? `Yes (${target.num_vulnerabilities} vulnerabilities found)` : "No"}</Td>
<Td>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<DeleteIconButton onClick={ev => onDeleteButtonClick(ev, target.id)} />
</RestrictedComponent>
</Td>
</Tr>
)}
</Tbody>
</Table>
</>
}
</section>
}
Example #19
Source File: ConferenceCard.js From codeursenseine.com with MIT License | 4 votes |
ConferenceCard = ({ conference, speakers }) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const capitalizeFirstLetter = (string) =>
string.charAt(0).toUpperCase() + string.slice(1);
if (conference?.childMdx?.frontmatter?.type === "break") {
return (
<Card variant="primary" mt={2}>
<Stack align="center">
<Text>{conference?.childMdx?.frontmatter?.title}</Text>
</Stack>
</Card>
);
}
return (
<Stack>
<Grid
templateColumns={["repeat(1, 1fr)", "repeat(1, 1fr) repeat(1, 4fr)"]}
mt={3}
>
<Stack mr={3}>
<Flex
display={["none", "flex"]}
flexDirection="column"
justifyContent="space-between"
h="100%"
borderColor="blue.50"
borderStyle="solid"
borderTopWidth={1}
borderBottomWidth={1}
>
<Text color="blue.600">
{conference.childMdx.frontmatter.startHour}
</Text>
<Text color="blue.600">
{conference.childMdx.frontmatter.endHour}
</Text>
</Flex>
<Stack display={["block", "none"]} mb={2}>
<Text color="blue.600">
{`${conference.childMdx.frontmatter.startHour} - ${conference.childMdx.frontmatter.endHour}`}
</Text>
</Stack>
{conference.childMdx.frontmatter.isKeynote && (
<Badge colorScheme="brand" width="fit-content">
Keynote
</Badge>
)}
</Stack>
<Card
borderLeftWidth={2}
borderLeftColor="brand.600"
onClick={onOpen}
w="full"
isLink
>
<Heading fontSize="md">
{conference.childMdx.frontmatter.title}
</Heading>
{speakers?.map((speaker) => (
<SpeakerPreview
key={speaker.childMdx.frontmatter.slug}
speaker={speaker}
/>
))}
<Center>
<Button
colorScheme="brand"
variant="link"
width="fit-content"
mt={2}
>
Voir les détails et s'inscrire
</Button>
</Center>
</Card>
</Grid>
<Drawer size="md" isOpen={isOpen} placement="right" onClose={onClose}>
<DrawerOverlay>
<DrawerContent>
<DrawerCloseButton />
<DrawerHeader>
<Stack alignItems="center" display="flex" flexDirection="row">
<Text fontSize="sm" mt={2}>
{capitalizeFirstLetter(
dayjs(conference.childMdx.frontmatter.eventDate).format(
"dddd D MMM"
)
)}{" "}
{`${conference.childMdx.frontmatter.startHour} - ${conference.childMdx.frontmatter.endHour}`}
</Text>
{conference.childMdx.frontmatter.isKeynote && (
<Badge
ml={3}
h="fit-content"
colorScheme="brand"
width="fit-content"
>
Keynote
</Badge>
)}
</Stack>
<Text>{conference.childMdx.frontmatter.title}</Text>
<Stack mt={3}>
{speakers?.map((speaker) => (
<SpeakerPreview
key={speaker.childMdx.frontmatter.slug}
speaker={speaker}
/>
))}
</Stack>
</DrawerHeader>
<DrawerBody overflow="auto">
<MDXRenderer>{conference.childMdx.body}</MDXRenderer>
</DrawerBody>
{conference.childMdx.frontmatter.meetupLink && (
<DrawerFooter display="flex" flexDirection="column">
<Button isFullWidth variant="outline" mb={3} onClick={onClose}>
Fermer
</Button>
<Button
colorScheme="brand"
as={Link}
target="_blank"
to={conference.childMdx.frontmatter.meetupLink}
isFullWidth
>
S'inscrire
</Button>
</DrawerFooter>
)}
</DrawerContent>
</DrawerOverlay>
</Drawer>
</Stack>
);
}
Example #20
Source File: components.js From idena-web with MIT License | 4 votes |
export function ReplenishStakeDrawer({onSuccess, onError, ...props}) {
const {t, i18n} = useTranslation()
const [{state}] = useIdentity()
const {coinbase} = useAuthState()
const {data: balanceData} = useQuery({
queryKey: ['get-balance', coinbase],
queryFn: ({queryKey: [, address]}) => callRpc('dna_getBalance', address),
enabled: Boolean(coinbase),
staleTime: (BLOCK_TIME / 2) * 1000,
notifyOnChangeProps: 'tracked',
})
const {submit} = useReplenishStake({onSuccess, onError})
const formatDna = toLocaleDna(i18n.language, {
maximumFractionDigits: 5,
})
const isRisky = [
IdentityStatus.Candidate,
IdentityStatus.Newbie,
IdentityStatus.Verified,
].includes(state)
return (
<Drawer {...props}>
<DrawerHeader>
<Stack spacing="4">
<Center bg="blue.012" h="12" w="12" rounded="xl">
<WalletIcon boxSize="6" color="blue.500" />
</Center>
<Heading
color="brandGray.500"
fontSize="lg"
fontWeight={500}
lineHeight="base"
>
{t('Add stake')}
</Heading>
</Stack>
</DrawerHeader>
<DrawerBody fontSize="md">
<Stack spacing={30}>
<Stack>
<Text>
{t(
'Get quadratic staking rewards for locking iDNA in your identity stake.'
)}
</Text>
<Text>
{t('Current stake amount: {{amount}}', {
amount: formatDna(balanceData?.stake),
nsSeparator: '!!',
})}
</Text>
</Stack>
<Stack spacing="2.5">
<form
id="replenishStake"
onSubmit={e => {
e.preventDefault()
const formData = new FormData(e.target)
const amount = formData.get('amount')
submit({amount})
}}
>
<FormControl>
<FormLabel mx={0} mb="3">
{t('Amount')}
</FormLabel>
<DnaInput name="amount" />
<FormHelperText fontSize="md">
<Flex justify="space-between">
<Box as="span" color="muted">
{t('Available')}
</Box>
<Box as="span">{formatDna(balanceData?.balance)}</Box>
</Flex>
</FormHelperText>
</FormControl>
</form>
</Stack>
{isRisky && (
<ErrorAlert>
{state === IdentityStatus.Verified
? t(
'You will lose 100% of the Stake if you fail the upcoming validation'
)
: t(
'You will lose 100% of the Stake if you fail or miss the upcoming validation'
)}
</ErrorAlert>
)}
</Stack>
</DrawerBody>
<DrawerFooter>
<HStack>
<SecondaryButton onClick={props.onClose}>
{t('Not now')}
</SecondaryButton>
<PrimaryButton form="replenishStake" type="submit">
{t('Add stake')}
</PrimaryButton>
</HStack>
</DrawerFooter>
</Drawer>
)
}
Example #21
Source File: components.js From idena-web with MIT License | 4 votes |
// eslint-disable-next-line react/prop-types
export function KillForm({isOpen, onClose}) {
const {t} = useTranslation()
const {privateKey, coinbase} = useAuthState()
const [, {killMe}] = useIdentity()
const [submitting, setSubmitting] = useState(false)
const toast = useToast()
const [to, setTo] = useState()
const {
data: {stake},
} = useQuery(['get-balance', coinbase], () => fetchBalance(coinbase), {
initialData: {balance: 0, stake: 0},
enabled: !!coinbase,
})
const terminate = async () => {
try {
if (to !== coinbase)
throw new Error(t('You must specify your own identity address'))
setSubmitting(true)
await killMe(privateKey)
toast({
status: 'success',
// eslint-disable-next-line react/display-name
render: () => <Toast title={t('Transaction sent')} />,
})
if (onClose) onClose()
} catch (error) {
toast({
// eslint-disable-next-line react/display-name
render: () => (
<Toast
title={error?.message ?? t('Error while sending transaction')}
status="error"
/>
),
})
} finally {
setSubmitting(false)
}
}
return (
<Drawer isOpen={isOpen} onClose={onClose}>
<DrawerHeader mb={6}>
<Center flexDirection="column">
<Avatar address={coinbase} />
<Heading
fontSize="lg"
fontWeight={500}
color="brandGray.500"
mt={4}
mb={0}
>
{t('Terminate identity')}
</Heading>
</Center>
</DrawerHeader>
<DrawerBody>
<Text fontSize="md" mb={6}>
{t(`Terminate your identity and withdraw the stake. Your identity status
will be reset to 'Not validated'.`)}
</Text>
<FormControlWithLabel label={t('Withraw stake, iDNA')}>
<Input value={stake} isDisabled />
</FormControlWithLabel>
<Text fontSize="md" mb={6} mt={6}>
{t(
'Please enter your identity address to confirm termination. Stake will be transferred to the identity address.'
)}
</Text>
<FormControlWithLabel label={t('Address')}>
<Input value={to} onChange={e => setTo(e.target.value)} />
</FormControlWithLabel>
</DrawerBody>
<DrawerFooter>
<HStack justify="flex-end">
<PrimaryButton
onClick={terminate}
isLoading={submitting}
colorScheme="red"
_hover={{
bg: 'rgb(227 60 60)',
}}
_active={{
bg: 'rgb(227 60 60)',
}}
_focus={{
boxShadow: '0 0 0 3px rgb(255 102 102 /0.50)',
}}
>
{t('Terminate')}
</PrimaryButton>
</HStack>
</DrawerFooter>
</Drawer>
)
}
Example #22
Source File: containers.js From idena-web with MIT License | 4 votes |
export function ReviewAdDrawer({
ad,
onDeployContract,
onStartVoting,
...props
}) {
const {t} = useTranslation()
const coinbase = useCoinbase()
const balance = useBalance(coinbase)
const failToast = useFailToast()
const [isPending, {on: setIsPendingOn, off: setIsPendingOff}] = useBoolean()
const {submit} = useReviewAd({
onBeforeSubmit: setIsPendingOn,
onDeployContract,
onStartVoting: React.useCallback(
data => {
onStartVoting(data)
setIsPendingOff()
},
[onStartVoting, setIsPendingOff]
),
onError: React.useCallback(
error => {
failToast(error)
setIsPendingOff()
},
[failToast, setIsPendingOff]
),
})
const {data: deployAmount} = useDeployContractAmount()
const {data: startAmount} = useStartAdVotingAmount()
const formatDna = useFormatDna({maximumFractionDigits: 5})
return (
<AdDrawer
isMining={isPending}
closeOnOverlayClick={!isPending}
closeOnEsc={!isPending}
isCloseable={!isPending}
{...props}
>
<DrawerHeader>
<Stack spacing={4}>
<Center
alignSelf="flex-start"
bg="blue.012"
w={12}
minH={12}
rounded="xl"
>
<OracleIcon boxSize={6} color="blue.500" />
</Center>
<Heading color="gray.500" fontSize="lg" fontWeight={500}>
{t('Send to Oracle Voting')}
</Heading>
</Stack>
</DrawerHeader>
<DrawerBody overflowY="auto" mx={-6} mb={10}>
<Stack spacing={6} color="gray.500" fontSize="md" p={6} pt={0}>
<Stack spacing={3}>
<Text>
{t(`Please keep in mind that you will not be able to edit the banner
after it has been submitted for verification`)}
</Text>
</Stack>
<Stack spacing={6} bg="gray.50" p={6} rounded="lg">
<Stack isInline spacing={5} align="flex-start">
<AdImage src={adImageThumbSrc(ad)} w="10" />
<Box>
<Text fontWeight={500}>{ad.title}</Text>
<ExternalLink href={ad.url} maxW="48">
{ad.url}
</ExternalLink>
</Box>
</Stack>
<Stack spacing={3}>
<HDivider />
<InlineAdStatGroup labelWidth="20">
<SmallInlineAdStat label={t('Language')} value={ad.language} />
<SmallInlineAdStat label={t('Min stake')} value={ad.stake} />
<SmallInlineAdStat label={t('Min age')} value={ad.age} />
<SmallInlineAdStat label={t('OS')} value={ad.os} />
</InlineAdStatGroup>
</Stack>
</Stack>
<form
id="reviewForm"
onSubmit={async e => {
e.preventDefault()
const {thumb, media} = await db.table('ads').get(ad.id)
const errors = validateAd({...ad, thumb, media})
if (Object.values(errors).some(Boolean)) {
failToast({
title: t('Unable to send invalid ad'),
description: t(`Please check {{fields}} fields`, {
fields: Object.entries(errors)
.filter(([, v]) => Boolean(v))
.map(([k]) => k)
.join(', '),
}),
})
return
}
if (deployAmount && startAmount) {
const requiredAmount = deployAmount + startAmount
if (balance > requiredAmount) {
try {
submit({
...ad,
thumb: new Uint8Array(
await compressAdImage(await thumb.arrayBuffer(), {
width: 80,
height: 80,
type: thumb.type,
})
),
media: new Uint8Array(
await compressAdImage(await media.arrayBuffer(), {
width: 320,
height: 320,
type: thumb.type,
})
),
})
} catch (error) {
failToast({
title: t('Error compressing images'),
description: error?.message,
})
}
} else {
failToast(
t(
`Insufficient funds to start reviewing ad. Please deposit at least {{missingAmount}}.`,
{
missingAmount: formatDna(
Math.abs(balance - requiredAmount)
),
}
)
)
}
}
}}
>
<Stack spacing={4}>
<FormControl isDisabled isReadOnly>
<Stack spacing={3}>
<FormLabel htmlFor="stake" mb={0}>
{t('Min stake, iDNA')}
</FormLabel>
<Input defaultValue={deployAmount} />
</Stack>
</FormControl>
<FormControl isDisabled isReadOnly>
<Stack spacing={3}>
<FormLabel htmlFor="oracleFee" mb={0}>
{t('Review fee, iDNA')}
</FormLabel>
<Input defaultValue={startAmount} />
</Stack>
</FormControl>
</Stack>
</form>
</Stack>
</DrawerBody>
<DrawerFooter bg="white">
<PrimaryButton
type="submit"
form="reviewForm"
isLoading={isPending}
loadingText={t('Mining...')}
>
{t('Send')}
</PrimaryButton>
</DrawerFooter>
</AdDrawer>
)
}
Example #23
Source File: index.js From UpStats with MIT License | 4 votes |
export default function Home({ status, systems, config }) {
console.log(status);
console.log(systems);
const [email, setEmail] = useState("");
const toast = useToast();
const handleSubmit = async (email) => {
try {
await http.post("/subs", { email: email });
toast({
title: "Success",
description: "Successfully Subscribed ",
status: "success",
duration: 9000,
isClosable: true,
});
} catch (ex) {
toast({
title: "Error",
description: "Submit Unsuccessful",
status: "error",
duration: 9000,
isClosable: true,
});
}
};
return (
<>
<Head>
<meta charSet="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<title>UP Stats</title>
<link rel="stylesheet" href="/main.css" />
</Head>
<main className="root">
<header className="top-0">
<nav>
<div className="content-center p-4">
{/* Nav Bar Logo */}
<img className="nav-brand" src="assets/img/logo.jpg" />
</div>
</nav>
</header>
<section>
<Center mt="5">
<Box bg="blue" w="90%" p={4} color="white" borderRadius="md">
{status.operational
? "All Systems Operational"
: `${status.outageCount} Systems Outage`}
</Box>
</Center>
<br />
<VStack>
{systems.map((system) => (
<Flex
id={system._id}
borderRadius="md"
boxShadow="lg"
w="90%"
p={3}
bg="white"
>
<Text pl={3}>{system.name}</Text>
<Spacer />
{system.status === "up" && (
<CheckCircleIcon mr={5} mt="1" color="green" />
)}
{system.status === "down" && (
<WarningIcon mr={5} mt="1" color="red" />
)}
</Flex>
))}
</VStack>
</section>
{config.mailing ? (
<VStack p={10} m={10} borderWidth={1} borderRadius="lg">
<h1 className="font-sans text-xl">Want to see Back in action?</h1>
<p className="font-sans">
Subscribe via Email and <br />
Get notified about the System Status
</p>
<Center>
<FormControl id="email" width="90%">
<FormLabel>Email address</FormLabel>
<Input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Box
width="8em"
mt="3"
height="3em"
border="1px"
color="white"
bg="blue"
borderRadius="lg"
p="3"
onClick={() => handleSubmit(email)}
>
<EmailIcon mr={3} />
Subscribe
</Box>
</FormControl>
</Center>
</VStack>
) : (
""
)}
<footer className="px-4 py-16 mx-auto max-w-7xl">
<nav className="grid grid-cols-2 gap-12 mb-12 md:grid-cols-3 lg:grid-cols-5">
<div>
<p className="mb-4 text-sm font-medium text-primary">
Handy Links
</p>
<a
className="flex mb-3 text-sm font-medium text-gray-700 transition md:mb-2 hover:text-primary"
href="https://github.com/ToolsHD/UPStats"
>
Opensource
</a>
<a
className="flex mb-3 text-sm font-medium text-gray-700 transition md:mb-2 hover:text-primary"
href="#"
>
Features
</a>
<a
className="flex mb-3 text-sm font-medium text-gray-700 transition md:mb-2 hover:text-primary"
href="#"
>
Pricing
</a>
</div>
</nav>
<div className="flex flex-col items-center justify-between md:flex-row">
<a href="/" className="mb-4 md:mb-0">
<img id="footer-img" src="assets/img/footer.jpg" />
<span className="sr-only">UpStats</span>
</a>
<p className="text-sm text-center text-gray-600 md:text-left">
© 2021 <a href="#">UP Stats</a>
</p>
</div>
</footer>
<div>
<button onClick="topFunction()" id="scroll-to-top">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M5 10l7-7m0 0l7 7m-7-7v18"
/>
</svg>
</button>
</div>
</main>
</>
);
}