@chakra-ui/react#Tag JavaScript Examples
The following examples show how to use
@chakra-ui/react#Tag.
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: components.js From idena-web with MIT License | 6 votes |
function ProfileTag({children, ...props}) {
return (
<Tag
bg={[null, 'gray.016']}
borderRadius={[null, 'xl']}
borderBottomWidth={[1, 0]}
borderBottomColor="gray.100"
color="gray.500"
fontSize={['base', 'sm']}
px={[null, '3']}
pt={['2', 0]}
pb={['2.5', 0]}
w={['full', null]}
{...props}
>
<Stack direction={['column', 'row']} spacing={['1.5', '1']} w={['full']}>
{children}
</Stack>
</Tag>
)
}
Example #2
Source File: Podcast.js From grandcast.fm with Apache License 2.0 | 6 votes |
Podcast = ({ podcast }) => {
const { title, itunesId, description, artwork, categories } = podcast
const [subscribeMutation, { data }] = useMutation(PODCAST_SUBSCRIBE)
return (
<Flex rounded="lg" borderWidth="2px" m={4}>
<Box width="200px">
<Image src={artwork} boxSize="200px" />
<Button
width="100%"
onClick={() =>
subscribeMutation({ variables: { itunesID: itunesId } })
}
>
<AddIcon />
</Button>
</Box>
<Box m={4} maxWidth="300px">
<Heading noOfLines={2}>{title}</Heading>
<Text noOfLines={3}>{description}</Text>
<Stack isInline>
{categories.slice(0, 3).map((c) => {
return <Tag key={c}>{c}</Tag>
})}
</Stack>
</Box>
</Flex>
)
}
Example #3
Source File: GreenTag.js From DAOInsure with MIT License | 5 votes |
function GreenTag({ children }) {
return (
<Tag borderRadius="full" ml={2} color="white" fontWeight="600" backgroundColor="lightgreen">
{children}
</Tag>
)
}
Example #4
Source File: Tags.js From web-client with Apache License 2.0 | 5 votes |
Tags = ({ values }) => {
if (!values) return null;
return JSON.parse(values)
.map((value, index) => <Tag key={`tag_index_${index}`} size="sm"><Link to={`/search/${value}?entities=commands,vulnerabilities`}>{value}</Link></Tag>);
}
Example #5
Source File: ClaimsList.js From DAOInsure with MIT License | 4 votes |
function ClaimsList({ claims }) {
let history = useHistory();
return (
<VStack alignItems='flex-start' width='100%' spacing={4}>
{claims.map((claim) => {
return (
<VStack
key={claim[0].toNumber()}
alignItems='flex-start'
borderStyle='solid'
borderWidth='1px'
borderRadius='10px'
borderColor='whatsapp.500'
px={6}
py={4}
width='100%'>
<HStack
justifyItems='flex-start'
alignItems='flex-start'
width='100%'>
<Box>
<HStack>
<Box
borderStyle='solid'
borderWidth='2px'
borderRadius='full'
borderColor='whatsapp.500'
padding='2px'>
<Avatar
size='sm'
icon={
<Jazzicon
diameter='32'
address={claim[1]}
/>
}
/>
</Box>
<Text>{claim[1]}</Text>
<Tag
colorScheme='whatsapp'
fontWeight='600'>
? : {claim[4].toNumber()}
</Tag>
<Tag
colorScheme='whatsapp'
fontWeight='600'>
? : {claim[5].toNumber()}
</Tag>
</HStack>
</Box>
<Spacer />
</HStack>
<Link
cursor='pointer'
to={`/voting/${claim[0].toNumber()}`}>
<Heading fontSize='20px' textColor='whatsapp.500'>
{claim[2]}
</Heading>
</Link>
<Text>{claim.claimSummary}</Text>
<Text fontWeight='600'>{claim.startTime}</Text>
</VStack>
);
})}
</VStack>
);
}
Example #6
Source File: InformationCards.js From DAOInsure with MIT License | 4 votes |
function InformationCards({
author,
loadingClaim,
dateOfIncident,
ipfsHash,
yesVotes,
noVotes,
rainData,
memberData,
}) {
const voters = [""];
const [openWeatherStats, setOpenWeatherStats] = useState();
useEffect(() => {
async function init() {
let response = await axios.get(
"https://api.openweathermap.org/data/2.5/onecall/timemachine?lat=32.21&lon=76.32&exclude=minutely,hourly&appid=162ac7d2a16586444f5b2e968f020e4c&dt=1628319601"
);
setOpenWeatherStats(response.data.hourly);
}
init();
}, []);
return (
<VStack spacing={5}>
<Card cardTitle='Information'>
<HStack width='100%'>
<Text fontWeight='600'>Author</Text>
<Spacer />
{loadingClaim ? (
<Skeleton isLoaded={!loadingClaim}>Author</Skeleton>
) : (
<Text>{`${author.substr(0, 7)}...${author.substr(
-7
)}`}</Text>
)}
</HStack>
<HStack width='100%'>
<Text fontWeight='600'>IPFS</Text>
<Spacer />
{loadingClaim ? (
<Skeleton isLoaded={!loadingClaim}>IPFS hash</Skeleton>
) : (
<HStack>
<a
href={`https://ipfs.io/ipfs/` + ipfsHash}
target='_blank'>
<Text>
{" "}
{`${ipfsHash.substr(
0,
7
)}...${ipfsHash.substr(-7)}`}{" "}
</Text>
<FaExternalLinkAlt size='10px' />
</a>
</HStack>
)}
</HStack>
<HStack width='100%'>
<Text fontWeight='600'>Member location</Text>
<Spacer />
{loadingClaim ? (
<Skeleton isLoaded={!loadingClaim}>Author</Skeleton>
) : (
<a
target='_blank'
href={
`https://www.google.co.in/maps/@` +
memberData.lat +
`,` +
memberData.long
}>
Map
</a>
)}
</HStack>
</Card>
<Card cardTitle='Time'>
<VStack width='100%'>
<HStack width='100%'>
<Text fontWeight='600'>Date Of Incident</Text>
<Spacer />
{loadingClaim ? (
<Skeleton isLoaded={!loadingClaim}>
Date Of Incident
</Skeleton>
) : (
<HStack>
<Text>{dateOfIncident}</Text>
</HStack>
)}
</HStack>
</VStack>
</Card>
<ChainlinkCard cardTitle=''>
<VStack width='100%'>
<HStack width='100%'>
<Text fontWeight='600'>Rain data : </Text>
<Text fontWeight='600'>{rainData} mm</Text>
<Spacer />
</HStack>
</VStack>
</ChainlinkCard>
<Card cardTitle='Current Results'>
<VStack width='100%'>
<HStack width='100%'>
<Text fontWeight='600'>Yes</Text>
<Spacer />
{loadingClaim ? (
<Skeleton>vote percent</Skeleton>
) : (
<Text fontWeight='600'>
{(yesVotes / (yesVotes + noVotes)) * 100
? (yesVotes / (yesVotes + noVotes)) * 100
: "0"}
%
</Text>
)}
</HStack>
<Progress
width='100%'
borderRadius='20px'
background='gray.300'
height='10px'
value={
loadingClaim
? 0
: (yesVotes / (yesVotes + noVotes)) * 100
}
colorScheme='green'
size='lg'
/>
<HStack width='100%'>
<Text fontWeight='600'>No</Text>
<Spacer />
{loadingClaim ? (
<Skeleton>vote percent</Skeleton>
) : (
<Text fontWeight='600'>
{(noVotes / (yesVotes + noVotes)) * 100
? (noVotes / (yesVotes + noVotes)) * 100
: "0"}
%
</Text>
)}
</HStack>
<Progress
width='100%'
borderRadius='20px'
background='gray.300'
height='10px'
value={
loadingClaim ? 0 : noVotes / (yesVotes + noVotes)
}
colorScheme='green'
size='lg'
/>
</VStack>
</Card>
<Card cardTitle='OpenWeather Analysis'>
{openWeatherStats ? (
<>
{openWeatherStats.map((stat) => {
return (
<HStack width='100%'>
<Text>
{new Date(parseInt(stat.dt) * 1000)
.toTimeString()
.substr(0, 5)}
</Text>
<Text>
{stat.weather[0].description[0].toUpperCase() +
stat.weather[0].description.substr(
1
)}
</Text>
<Spacer />
<Image
src={`http://openweathermap.org/img/wn/${stat.weather[0].icon}.png`}
/>
</HStack>
);
})}
</>
) : (
<Spinner margin='auto' />
)}
</Card>
<Card cardTitle='Votes'>
<VStack width='100%' alignItems='flex-start'>
{loadingClaim ? (
<HStack justifyContent='space-between' width='100%'>
<HStack>
<SkeletonCircle />
<Skeleton>Address that voted</Skeleton>
</HStack>
<Skeleton>Vote</Skeleton>
<Skeleton>Voting Power</Skeleton>
</HStack>
) : (
<>
{voters.map((voter) => {
return (
<HStack
justifyContent='space-between'
width='100%'
key={0}>
<HStack>
<Avatar
size='xs'
icon={
<Jazzicon
diameter='24'
address='0x8Cf24E66d1DC40345B1bf97219856C8140Ce6c69'
/>
}
/>
<Tag>{`${"0x8Cf24E66d1DC40345B1bf97219856C8140Ce6c69".substr(
0,
6
)}...${"0x8Cf24E66d1DC40345B1bf97219856C8140Ce6c69".substr(
-5
)}`}</Tag>
</HStack>
<Tag colorScheme='whatsapp'>Yes</Tag>
<Text>300 DIx</Text>
</HStack>
);
})}
</>
)}
</VStack>
</Card>
</VStack>
);
}
Example #7
Source File: Profile.js From DAOInsure with MIT License | 4 votes |
function Profile() {
const web3Context = useContext(Web3Context);
const {
signerAddress,
userDaoTokenBalance,
fetchProposals,
fetchVotedProposals,
proposalsArray,
votedProposalsArray,
} = web3Context;
const [daoTokenBalance, setDaoTokenBalance] = useState(0);
const [stable, setStable] = useState(false);
useEffect(() => {
setInterval(async () => {
setDaoTokenBalance(await userDaoTokenBalance());
}, 10000);
}, []);
useEffect(() => {
fetchProposals();
fetchVotedProposals();
}, [stable]);
function con() {
console.log(proposalsArray);
}
return (
<VStack
alignItems='flex-start'
height='calc(100vh - 64px)'
px='250px'
py='20px'
width='100%'>
<HStack width='100%' alignItems='flex-start'>
<Box
borderWidth='2px'
borderRadius='full'
borderColor='whatsapp.500'
padding='2px'>
<Avatar
size='md'
icon={
<Jazzicon
diameter='48'
address={`${signerAddress}`}
/>
}
/>
</Box>
<VStack alignItems='flex-start'>
<Heading fontSize='20px'>{signerAddress}</Heading>
<Tag>10DAIx / month</Tag>
</VStack>
<Spacer />
<VStack>
<Tag>INSURE Tokens : {daoTokenBalance}</Tag>
</VStack>
</HStack>
<Grid
width='100%'
mt='30px !important'
templateColumns='3fr 2fr'
gridGap={5}
alignItems='flex-start'>
<Tabs
colorScheme='whatsapp'
variant='soft-rounded'
width='100%'>
<TabList>
<Tab onClick={con}>
Claims{" "}
<Tag ml={2} borderRadius='20px'>
{proposalsArray.length}
</Tag>
</Tab>
<Tab>
Voted For
<Tag ml={2} borderRadius='20px'>
{votedProposalsArray.length}
</Tag>
</Tab>
</TabList>
<TabPanels>
<TabPanel mt={3} padding={0}>
<Card cardTitle='Claims'>
<Table>
<Tbody>
{proposalsArray.map(function (
element,
id
) {
return (
<Tr key={id}>
<Th>
{" "}
{element[0].toNumber()}{" "}
</Th>
<Th>{element[2]}</Th>
<Th>
{element[7] ? (
<span>
{" "}
Passed{" "}
</span>
) : (
<span>
{" "}
Failed{" "}
</span>
)}
</Th>
</Tr>
);
})}
</Tbody>
</Table>
</Card>
</TabPanel>
<TabPanel mt={3} padding={0}>
<Card cardTitle='Claims'>
<Table>
<Tbody>
{votedProposalsArray.map(function (
element,
id
) {
return (
<Tr key={id}>
<Th>
{" "}
{element[0].toNumber()}{" "}
</Th>
<Th>{element[2]}</Th>
<Th>
{element[7] ? (
<span>
{" "}
Passed{" "}
</span>
) : (
<span>
{" "}
Failed{" "}
</span>
)}
</Th>
</Tr>
);
})}
</Tbody>
</Table>
</Card>
</TabPanel>
</TabPanels>
</Tabs>
</Grid>
</VStack>
);
}
Example #8
Source File: VotingPage.js From DAOInsure with MIT License | 4 votes |
function VotingPage(props) {
const { textileClient } = useContext(AppContext);
const [state, dispatch] = useReducer(stateReducer, {
currentImage: "",
sendImage: "",
message: "",
messages: [],
claim: "",
loadingClaim: true,
vote: 0,
});
const { id } = useParams();
const {
allProposalsArray,
fetchAllProposals,
voteOnProposal,
signerAddress,
claimProposal,
fetchMemberInfo,
memberData,
} = useContext(Web3Context);
const { getRootProps, getRadioProps } = useRadioGroup({
name: "Vote",
defaultValue: "No",
onChange: (e) => handleRadioChange(e),
});
useEffect(() => {
async function init() {
const proposalId = allProposalsArray[id][9];
const myFile = await queryThread(
textileClient,
"bafkyspsyykcninhqn4ht6d6jeqmzq4cepy344akmkhjk75dmw36wq4q",
"claimsData",
{ claimId: proposalId }
);
// const myFile = await fleekStorage.getFileFromHash({
// hash: proposalId,
// });
dispatch({ type: ACTIONS.SET_CLAIM, payload: myFile });
dispatch({ type: ACTIONS.SET_LOADING_CLAIM, payload: false });
// messages from the chat feature are stored in textile. A single collection of all message but can be distinguished using claimId.
let messages = await queryThread(
textileClient,
"bafkyspsyykcninhqn4ht6d6jeqmzq4cepy344akmkhjk75dmw36wq4q",
"messagesData",
{ claimId: id }
);
dispatch({ type: ACTIONS.SET_MESSAGES, payload: messages });
console.log("listening");
// listener for new messages that are added to the collection.
let closer = await textileClient.listen(
ThreadID.fromString(
"bafkyspsyykcninhqn4ht6d6jeqmzq4cepy344akmkhjk75dmw36wq4q"
),
[{ actionTypes: ["CREATE"], collectionName: "messagesData" }],
(reply, error) => {
dispatch({
type: ACTIONS.SET_MESSAGES,
payload: [reply.instance],
});
}
);
// close listener
return function cleanup() {
closer();
};
}
if (textileClient) {
init();
}
}, [textileClient]);
useEffect(() => {
fetchMemberInfo();
}, []);
const options = ["Yes", "No"];
const group = getRootProps();
const handleImage = ({ target }) => {
dispatch({ type: ACTIONS.SET_CURR_IMAGE, payload: target.src });
};
const handleRadioChange = (e) => {
if (e == "Yes") {
dispatch({ type: ACTIONS.SET_VOTE, payload: 1 });
} else {
dispatch({ type: ACTIONS.SET_VOTE, payload: 0 });
}
};
const handleMessage = ({ target }) => {
dispatch({ type: ACTIONS.SET_MESSAGE, payload: target.value });
};
const handleSendImageChange = ({ target }) => {
dispatch({ type: ACTIONS.SET_SEND_IMAGE, payload: target.files[0] });
};
const handleSendMessage = async () => {
let uploadedImage = "";
// upload image if any in message to slate.
if (state.sendImage) {
let result = await uploadToSlate(state.sendImage);
uploadedImage = `https://slate.textile.io/ipfs/${result.data.cid}`;
}
let messageObj = {
message: state.message,
image: uploadedImage,
address: signerAddress,
claimId: id,
};
let resultFromTextile = await addToThread(
textileClient,
"bafkyspsyykcninhqn4ht6d6jeqmzq4cepy344akmkhjk75dmw36wq4q",
"messagesData",
messageObj
);
dispatch({ type: ACTIONS.SET_MESSAGE, payload: "" });
dispatch({ type: ACTIONS.SET_SEND_IMAGE, payload: "" });
};
return (
<Grid
px='250px'
py='20px'
width='100%'
templateColumns='3fr 2fr'
gridGap={5}
alignItems='flex-start'>
<VStack alignItems='flex-start' width='100%'>
{state.loadingClaim ? (
<>
<HStack width='100%' justifyContent='space-between'>
<Skeleton isLoaded={!state.loadingClaim}>
Loading Claim
</Skeleton>
<Skeleton isLoaded={!state.loadingClaim}>
Claim Status
</Skeleton>
</HStack>
<Skeleton width='100%'>
<Box height='300px' width='100%'>
Image
</Box>
</Skeleton>
</>
) : (
<>
<HStack width='100%' justifyContent='space-between'>
<Heading fontSize='24px'>
{state.claim.claimTitle}
</Heading>
<Tag>Open</Tag>
</HStack>
{state.claim.images.length == 0 ? null : (
<>
<Box
mt='10px !important'
boxShadow='lg'
borderRadius='10px'>
<Image
borderRadius='10px'
src={state.currentImage}
/>
</Box>
<HStack>
{state.claim.images.map((image) => {
return (
<Image
onClick={handleImage}
borderRadius='10px'
height='70px'
src={image}
/>
);
})}
</HStack>
</>
)}
<Text>{state.claim.claimSummary}</Text>
</>
)}
{signerAddress == allProposalsArray[id][1] ? (
<Box
_hover={{ boxShadow: "base", transform: "scale(1.01)" }}
transition='all .3s'
textColor='white'
fontWeight='600'
width='30%'
backgroundColor='whatsapp.500'
borderRadius='20px'
textAlign='center'
py={2}
borderColor='whatsapp.500'
colorScheme='whatsapp'
onClick={() => claimProposal(id)}>
Claim
</Box>
) : (
<span> </span>
)}
<Card cardTitle='Cast Your Vote'>
{state.loadingClaim ? (
<Spinner margin='auto' borderColor='whatsapp.500' />
) : (
<>
<VStack width='100%' {...group}>
{options.map((value) => {
const radio = getRadioProps({ value });
return (
<RadioCard key={value} {...radio}>
{value}
</RadioCard>
);
})}
</VStack>
<Box
_hover={{
boxShadow: "base",
transform: "scale(1.01)",
}}
transition='all .3s'
textColor='white'
fontWeight='600'
width='100%'
backgroundColor='whatsapp.500'
borderRadius='20px'
textAlign='center'
py={2}
borderColor='whatsapp.500'
colorScheme='whatsapp'
onClick={() => voteOnProposal(id, state.vote)}>
Vote
</Box>
</>
)}
</Card>
<Card cardTitle='Chat'>
{state.loadingClaim ? (
<Spinner borderColor='whatsapp.500' margin='auto' />
) : (
<VStack
height='400px'
spacing={5}
justifyContent='flex-end'
width='100%'
alignItems='flex-start'>
<VStack
alignItems='flex-start'
overflowY='scroll'
width='100%'>
{state.messages.map((message) => {
return (
<HStack
key={message._id}
alignItems='flex-end'>
<Tooltip
placement='top'
hasArrow
label={`${message.address.substr(
0,
6
)}...${message.address.substr(
-4
)}`}>
<Box
borderWidth='2px'
padding='2px'
borderColor='whatsapp.500'
borderStyle='solid'
borderRadius='full'>
<Avatar
size='sm'
icon={
<Jazzicon
diameter='32'
address={
message.address
}
/>
}
/>
</Box>
</Tooltip>
<VStack
alignItems='flex-start'
backgroundColor='whatsapp.500'
color='white'
borderWidth='1px'
borderRadius='10px'
borderColor='whatsapp.500'
padding={3}>
{message.image.length > 0 ? (
<Image
borderRadius='10px'
height='200px'
src={message.image}
/>
) : null}
<Text>{message.message}</Text>
</VStack>
</HStack>
);
})}
</VStack>
<HStack>
{state.sendImage ? (
<HStack
borderColor='whatsapp.500'
borderWidth='1px'
padding={2}
borderRadius='10px'
key={state.sendImage.name}>
<MdImage />
<Text>{state.sendImage.name}</Text>
</HStack>
) : null}
</HStack>
<HStack width='100%'>
<InputGroup>
<Input
value={state.message}
onChange={handleMessage}
borderRadius='20px'
focusBorderColor='whatsapp.500'
/>
<InputRightElement>
<IconButton
cursor='pointer'
as='label'
htmlFor='image-input'
colorScheme='whatsapp'
icon={<ImAttachment />}
/>
<input
onChange={(e) =>
handleSendImageChange(e)
}
type='file'
id='image-input'
style={{ display: "none" }}
/>
</InputRightElement>
</InputGroup>
<Button
onClick={handleSendMessage}
colorScheme='whatsapp'>
Send
</Button>
</HStack>
</VStack>
)}
</Card>
</VStack>
{state.loadingClaim ? (
<InformationCards loadingClaim={state.loadingClaim} />
) : (
<InformationCards
author={state.claim.author}
// startDate={state.claim.startTime}
dateOfIncident={state.claim.dateOfIncident}
ipfsHash={allProposalsArray[id].ipfsHash}
yesVotes={allProposalsArray[id].yesVotes}
noVotes={allProposalsArray[id].noVotes}
rainData={allProposalsArray[id].rainData.toNumber()}
memberData={memberData}
/>
)}
</Grid>
);
}
Example #9
Source File: BuilderProfileView.jsx From scaffold-directory with MIT License | 4 votes |
export default function BuilderProfileView({ serverUrl, mainnetProvider, address, userProvider, userRole }) {
const { builderAddress } = useParams();
const { primaryFontColor, secondaryFontColor, borderColor, iconBgColor } = useCustomColorModes();
const [builder, setBuilder] = useState();
const [challengeEvents, setChallengeEvents] = useState([]);
const [isLoadingBuilder, setIsLoadingBuilder] = useState(false);
const [isBuilderOnBg, setIsBuilderOnBg] = useState(false);
const [isLoadingTimestamps, setIsLoadingTimestamps] = useState(false);
const toast = useToast({ position: "top", isClosable: true });
const toastVariant = useColorModeValue("subtle", "solid");
const challenges = builder?.challenges ? Object.entries(builder.challenges) : undefined;
const acceptedChallenges = getAcceptedChallenges(builder?.challenges);
const isMyProfile = builderAddress === address;
const fetchBuilder = async () => {
setIsLoadingBuilder(true);
const fetchedBuilder = await axios.get(serverUrl + `/builders/${builderAddress}`);
setBuilder(fetchedBuilder.data);
try {
await axios.get(bgBackendUrl + `/builders/${builderAddress}`);
} catch (e) {
// Builder Not found in BG
setIsLoadingBuilder(false);
return;
}
setIsBuilderOnBg(true);
setIsLoadingBuilder(false);
};
useEffect(() => {
fetchBuilder();
// eslint-disable-next-line
}, [builderAddress]);
useEffect(() => {
if (!builderAddress) {
return;
}
async function fetchChallengeEvents() {
setIsLoadingTimestamps(true);
try {
const fetchedChallengeEvents = await getChallengeEventsForUser(builderAddress);
setChallengeEvents(fetchedChallengeEvents.sort(byTimestamp).reverse());
setIsLoadingTimestamps(false);
} catch (error) {
toast({
description: "Can't get challenges metadata. Please try again",
status: "error",
variant: toastVariant,
});
}
}
fetchChallengeEvents();
// eslint-disable-next-line
}, [builderAddress]);
return (
<Container maxW="container.xl">
<SimpleGrid gap={14} columns={{ base: 1, xl: 4 }}>
<GridItem colSpan={1}>
<BuilderProfileCard
builder={builder}
mainnetProvider={mainnetProvider}
isMyProfile={isMyProfile}
userProvider={userProvider}
fetchBuilder={fetchBuilder}
userRole={userRole}
/>
</GridItem>
{isBuilderOnBg ? (
<GridItem colSpan={{ base: 1, xl: 3 }}>
<Box borderColor={borderColor} borderWidth={1} p={5}>
<Flex direction="column" align="center" justify="center">
<Image src="/assets/bg.png" mb={3} />
<Text mb={3} fontSize="lg" fontWeight="bold">
This builder has upgraded to BuidlGuidl.
</Text>
<Button as={Link} href={`${BG_FRONTEND_URL}/builders/${builderAddress}`} isExternal colorScheme="blue">
View their profile on Buidlguidl
</Button>
</Flex>
</Box>
</GridItem>
) : (
<GridItem colSpan={{ base: 1, xl: 3 }}>
<HStack spacing={4} mb={8}>
<Flex borderRadius="lg" borderColor={borderColor} borderWidth={1} p={4} w="full" justify="space-between">
<Flex bg={iconBgColor} borderRadius="lg" w={12} h={12} justify="center" align="center">
<InfoOutlineIcon w={5} h={5} />
</Flex>
<div>
<Text fontSize="xl" fontWeight="medium" textAlign="right">
{acceptedChallenges.length}
</Text>
<Text fontSize="sm" color={secondaryFontColor} textAlign="right">
challenges completed
</Text>
</div>
</Flex>
<Flex borderRadius="lg" borderColor={borderColor} borderWidth={1} p={4} w="full" justify="space-between">
<Flex bg={iconBgColor} borderRadius="lg" w={12} h={12} justify="center" align="center">
<InfoOutlineIcon w={5} h={5} />
</Flex>
<div>
<Text fontSize="xl" fontWeight="medium" textAlign="right">
{builder?.function ? (
<Tag colorScheme={userFunctionDescription[builder?.function].colorScheme} variant="solid">
{userFunctionDescription[builder?.function].label}
</Tag>
) : (
"-"
)}
</Text>
<Text fontSize="sm" color={secondaryFontColor} textAlign="right">
Role
</Text>
</div>
</Flex>
</HStack>
<Flex mb={4}>
<Text fontSize="2xl" fontWeight="bold">
Challenges
</Text>
<Spacer />
</Flex>
{isLoadingBuilder && <BuilderProfileChallengesTableSkeleton />}
{!isLoadingBuilder &&
(challenges ? (
<Box overflowX="auto">
<Table>
{isMyProfile && (
<TableCaption>
<Button as={RouteLink} colorScheme="blue" to="/">
Start a challenge
</Button>
</TableCaption>
)}
<Thead>
<Tr>
<Th>Name</Th>
<Th>Contract</Th>
<Th>Live Demo</Th>
<Th>Updated</Th>
<Th>Status</Th>
</Tr>
</Thead>
<Tbody>
{challenges.map(([challengeId, lastSubmission]) => {
if (!challengeInfo[challengeId]) {
return null;
}
const lastEventForChallenge = challengeEvents.filter(
event => event.payload.challengeId === challengeId,
)[0];
return (
<Tr key={challengeId}>
<Td>
<Link as={RouteLink} to={`/challenge/${challengeId}`} fontWeight="700" color="teal.500">
{challengeInfo[challengeId].label}
</Link>
</Td>
<Td>
<Link
// Legacy branchUrl
href={lastSubmission.contractUrl || lastSubmission.branchUrl}
color="teal.500"
target="_blank"
rel="noopener noreferrer"
>
Code
</Link>
</Td>
<Td>
<Link
href={lastSubmission.deployedUrl}
color="teal.500"
target="_blank"
rel="noopener noreferrer"
>
Demo
</Link>
</Td>
<Td>
{isLoadingTimestamps ? (
<SkeletonText noOfLines={1} />
) : (
<DateWithTooltip timestamp={lastEventForChallenge?.timestamp} />
)}
</Td>
<Td>
<ChallengeStatusTag
status={lastSubmission.status}
comment={lastSubmission.reviewComment}
autograding={lastSubmission.autograding}
/>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
) : (
<Flex
justify="center"
align="center"
borderRadius="lg"
borderColor={borderColor}
borderWidth={1}
py={36}
w="full"
>
{isMyProfile ? (
<Box maxW="xs" textAlign="center">
<Text fontWeight="medium" color={primaryFontColor} mb={2}>
Start a new challenge
</Text>
<Text color={secondaryFontColor} mb={4}>
Show off your skills. Learn everything you need to build on Ethereum!
</Text>
<Button as={RouteLink} colorScheme="blue" to="/">
Start a challenge
</Button>
</Box>
) : (
<Box maxW="xs" textAlign="center">
<Text color={secondaryFontColor} mb={4}>
This builder hasn't completed any challenges.
</Text>
</Box>
)}
</Flex>
))}
</GridItem>
)}
</SimpleGrid>
</Container>
);
}
Example #10
Source File: Details.js From web-client with Apache License 2.0 | 4 votes |
VulnerabilityDetails = () => {
const navigate = useNavigate();
const { vulnerabilityId } = useParams();
const [vulnerability, updateVulnerability] = useFetch(`/vulnerabilities/${vulnerabilityId}`)
const deleteVulnerability = useDelete(`/vulnerabilities/`)
const parentType = 'vulnerability';
const parentId = vulnerabilityId;
const [attachments, reloadAttachments] = useFetch(`/attachments?parentType=${parentType}&parentId=${parentId}`)
const handleDelete = async () => {
const confirmed = await deleteVulnerability(vulnerabilityId);
if (confirmed)
navigate('/vulnerabilities')
}
const onStatusChange = ev => {
const [status, substatus] = ev.target.value.split('-');
secureApiFetch(`/vulnerabilities/${vulnerability.id}`, {
method: 'PATCH',
body: JSON.stringify({ status, substatus })
})
.then(() => {
actionCompletedToast("The status has been transitioned.");
updateVulnerability()
})
.catch(err => console.error(err))
}
if (!vulnerability) return <Loading />
if (vulnerability && vulnerability.is_template) {
return <Navigate to={`/vulnerabilities/templates/${vulnerability.id}`} />
}
return <div>
<div className='heading'>
<Breadcrumb>
<Link to="/vulnerabilities">Vulnerabilities</Link>
</Breadcrumb>
<HStack alignItems='flex-end'>
<RestrictedComponent roles={['administrator', 'superuser', 'user']}>
<EditButton onClick={(ev) => {
ev.preventDefault();
navigate(`/vulnerabilities/${vulnerability.id}/edit`)
}}>Edit</EditButton>
<label>Transition to
<Select onChange={onStatusChange} value={vulnerability.status + '-' + vulnerability.substatus}>
{VulnerabilityStatuses.map(status =>
<option key={`vulnstatus_${status.id}`} value={status.id}>{status.name}</option>
)}
</Select>
</label>
<DeleteButton onClick={handleDelete} />
</RestrictedComponent>
</HStack>
</div>
<article>
<PageTitle value={`${vulnerability.summary} vulnerability`} />
<Title type='Vulnerability' title={vulnerability.external_id ? <><strong>{vulnerability.external_id.toUpperCase()}</strong> {vulnerability.summary}</> : vulnerability.summary} icon={<IconFlag />} />
<Tag size="sm" colorScheme="blue">{vulnerability.visibility}</Tag> <Tags values={vulnerability.tags} />
<Tabs>
<TabList>
<Tab>Description</Tab>
<Tab>Remediation</Tab>
<Tab>Notes</Tab>
<Tab>Attachments</Tab>
</TabList>
<TabPanels>
<TabPanel>
<VulnerabilityDescriptionPanel vulnerability={vulnerability} />
</TabPanel>
<TabPanel>
<VulnerabilityRemediationPanel vulnerability={vulnerability} />
</TabPanel>
<TabPanel>
<VulnerabilitiesNotesTab vulnerability={vulnerability} />
</TabPanel>
<TabPanel>
<AttachmentsDropzone parentType={parentType} parentId={parentId} onUploadFinished={reloadAttachments} />
<h4><IconDocument />Attachment list</h4>
<AttachmentsTable attachments={attachments} reloadAttachments={reloadAttachments} />
</TabPanel>
</TabPanels>
</Tabs>
</article>
</div >
}