@chakra-ui/react#Skeleton JavaScript Examples
The following examples show how to use
@chakra-ui/react#Skeleton.
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: Card.js From DAOInsure with MIT License | 6 votes |
function Card({ cardTitle, backgroundColor, children, isLoading }) {
return (
<VStack borderRadius="10px" borderStyle="solid" borderColor="whatsapp.500" borderWidth="1px" width="100%" alignItems="flex-start">
<Box backgroundColor={backgroundColor} width="100%" borderBottomWidth="1px" borderColor="whatsapp.500" px="20px" py="20px">
<Skeleton isLoaded={!isLoading}>
<Heading fontSize="16px">
{cardTitle}
</Heading>
</Skeleton>
</Box>
<VStack alignItems="flex-start" px="20px" py="20px" width="100%">
{children}
</VStack>
</VStack>
);
}
Example #2
Source File: ChainlinkCard.js From DAOInsure with MIT License | 6 votes |
function Card({ cardTitle, backgroundColor, children, isLoading }) {
return (
<VStack
borderRadius="10px"
borderStyle="solid"
borderColor="blue"
borderWidth="1px"
width="100%"
alignItems="flex-start"
>
<Box
backgroundColor={backgroundColor}
width="100%"
borderBottomWidth="1px"
borderColor="blue"
px="15px"
py="15px"
>
<Skeleton isLoaded={!isLoading}>
<Heading fontSize="16px">
{" "}
<img src={ChainlinkLogo} width="90px" />
</Heading>
</Skeleton>
</Box>
<VStack alignItems="flex-start" px="20px" py="20px" width="100%">
{children}
</VStack>
</VStack>
);
}
Example #3
Source File: components.js From idena-web with MIT License | 6 votes |
export function CertificateTypeLabel({type}) {
switch (type) {
case CertificateType.Easy:
return (
<CertificateTypeLabelLayout bg="red.500">
{CertificateTypeTitle(type)}
</CertificateTypeLabelLayout>
)
case CertificateType.Medium:
return (
<CertificateTypeLabelLayout bg="gray.500">
{CertificateTypeTitle(type)}
</CertificateTypeLabelLayout>
)
case CertificateType.Hard:
return (
<CertificateTypeLabelLayout bg="orange.500">
{CertificateTypeTitle(type)}
</CertificateTypeLabelLayout>
)
default:
return (
<Skeleton
position="absolute"
transform="rotate(-45deg)"
w={40}
h={8}
top={7}
left={-9}
/>
)
}
}
Example #4
Source File: SkeletonAddress.jsx From scaffold-directory with MIT License | 6 votes |
SkeletonAddress = ({ fontSize, w }) => (
<HStack spacing="20px">
<Skeleton>
<span style={{ verticalAlign: "middle" }}>
<QRPunkBlockie withQr={false} address="0xf39F" w={w ?? 12.5} borderRadius="md" />
</span>
</Skeleton>
<Skeleton>
<span
style={{
verticalAlign: "middle",
fontSize: fontSize ?? 28,
fontWeight: "bold",
}}
>
0xf39F
</span>
</Skeleton>
</HStack>
)
Example #5
Source File: ProjectListFull.js From benjamincarlson.io with MIT License | 5 votes |
ProjectListFull = () => {
const [searchValue, setSearchValue] = useState('');
const { data, error } = useSWR('/api/projects', fetcher)
if (error) return <div style={{ width: '100%' }}>Failed to load projects! Please check your internet connection. If the error persists, contact me.</div>
if (!data) return (
<div style={{ width: '100%' }}>
<InputGroup mb={4} mr={4} w="100%">
<Input
aria-label="Search by name, description, and language"
placeholder="Search by name, description, and language"
/>
<InputRightElement children={<SearchIcon color="gray.500" />} />
</InputGroup>
<SimpleGrid minChildWidth="300px" spacing="40px">
{[...Array(10)].map((_, i) => (
<Skeleton key={i} h="250px" />
))}
</SimpleGrid>
</div>
)
const filteredProjects = Object(data.repos)
.filter((project) =>
project?.name?.toLowerCase().includes(searchValue.toLowerCase())
|| project?.description?.toLowerCase().includes(searchValue.toLowerCase())
|| project?.language?.toLowerCase().includes(searchValue.toLowerCase())
)
.sort(
(a, b) =>
Number(b.stars) - Number(a.stars)
)
return (
<>
<InputGroup mb={4} mr={4} w="100%">
<Input
aria-label="Search by name, description, and language"
onChange={(e) => setSearchValue(e.target.value)}
placeholder="Search by name, description, and language"
/>
<InputRightElement children={<SearchIcon color="gray.500" />} />
</InputGroup>
<SimpleGrid minChildWidth="300px" spacing="40px">
{!filteredProjects.length && <Text>No projects found for "<strong>{searchValue}</strong>"!</Text>}
{filteredProjects
.map((p, index) => (
<ProjectCard
key={index}
title={p.name}
description={p.description}
repoHref={p.url}
languageColor={getLanguageColor(p.language)}
language={p.language}
starCount={p.stars}
stargazersUrl={p.stargazers_url}
homepage={p.homepage}
/>
))}
</SimpleGrid>
</>
)
}
Example #6
Source File: NewsSkeleton.js From sided.news.web with MIT License | 5 votes |
export default function NewsSkeleton({}) {
return (
<div className={styles.news}>
<div className={styles.left_col}>
<Skeleton
height="100%"
style={{
borderTopLeftRadius: "20px",
borderBottomLeftRadius: "20px",
}}
/>
</div>
<div className={styles.right_col}>
<div className={styles.news_title}>
<SkeletonText mt="4" noOfLines={4} spacing="4" />
</div>
<div>
<div className={styles.buttons}>
<div>
<Button colorScheme="teal" size="xs">
Read More
</Button>
</div>
<div>
<Link href="/">
<Button colorScheme="teal" size="xs" variant="outline">
Source
</Button>
</Link>
</div>
</div>
<div className={styles.date}>
{" "}
<Skeleton height="16px" />
</div>
</div>
</div>
</div>
);
}
Example #7
Source File: components.js From idena-web with MIT License | 5 votes |
function FullSkeleton(props) {
return <Skeleton w="full" {...props} />
}
Example #8
Source File: BuilderProfileCard.jsx From scaffold-directory with MIT License | 5 votes |
BuilderProfileCardSkeleton = ({ isLoaded, children }) => (
<Skeleton isLoaded={isLoaded}>{isLoaded ? children() : <SkeletonText mt="4" noOfLines={4} spacing="4" />}</Skeleton>
)
Example #9
Source File: BuilderProfileChallengesTableSkeleton.jsx From scaffold-directory with MIT License | 5 votes |
BuilderProfileChallengesTableSkeleton = () => (
<Box overflowX="auto">
<Table>
<Thead>
<Tr>
<Th w="30%">Name</Th>
<Th>Contract</Th>
<Th>Live Demo</Th>
<Th>Updated</Th>
<Th>Status</Th>
</Tr>
</Thead>
<Tbody>
{[1, 2].map(lineNumber => {
return (
<Tr key={lineNumber}>
<Td>
<SkeletonText noOfLines={1} py={2} />
</Td>
<Td>
<SkeletonText noOfLines={1} w="50%" />
</Td>
<Td>
<SkeletonText noOfLines={1} w="50%" />
</Td>
<Td>
<SkeletonText noOfLines={1} />
</Td>
<Td>
<Skeleton h={6} w={20} borderRadius="full">
Submitted
</Skeleton>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
)
Example #10
Source File: SubmissionReviewTableSkeleton.jsx From scaffold-directory with MIT License | 5 votes |
BuildsTableSkeleton = () => (
<Box overflowX="auto">
<Table mb={4}>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Build Name</Th>
<Th>Description</Th>
<Th>Branch URL</Th>
<Th>Submitted time</Th>
<Th>Actions</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={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<HStack spacing={3}>
<Skeleton startColor="red.100" endColor="red.500">
<Button type="button" size="xs">
Reject
</Button>
</Skeleton>
<Skeleton startColor="green.100" endColor="green.500">
<Button type="button" style={{ marginRight: 10 }} size="xs">
Approve
</Button>
</Skeleton>
</HStack>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
)
Example #11
Source File: SubmissionReviewTableSkeleton.jsx From scaffold-directory with MIT License | 5 votes |
ChallengesTableSkeleton = () => (
<Box overflowX="auto">
<Table mb={4}>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Challenge</Th>
<Th>Contract</Th>
<Th>Live demo</Th>
<Th>Submitted time</Th>
<Th>Actions</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={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<SkeletonText noOfLines={1} py={4} />
</Td>
<Td>
<Skeleton startColor="blue.100" endColor="blue.500">
<Button type="button" size="xs">
Review
</Button>
</Skeleton>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
)
Example #12
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 #13
Source File: MakeClaim.js From DAOInsure with MIT License | 4 votes |
function MakeClaim() {
const [currentImage, setCurrentImage] = useState(undefined);
const [images, setImages] = useState([]);
const [isPageLoading, setIsPageLoading] = useState(false);
const { textileClient } = useContext(AppContext);
const [claimTitle, setClaimTitle] = useState();
const [claimSummary, setClaimSummary] = useState();
const [dateOfIncident, setDateOfIncident] = useState();
const [startTime, setStartTime] = useState();
const web3Context = useContext(Web3Context);
const {
createProposal,
signerAddress,
claimableAmount,
getClaimableAmount,
} = web3Context;
useEffect(() => {
getClaimableAmount();
}, []);
const handleImage = async (e) => {
console.log("uploading");
let file = e.target.files[0];
try {
let result = await uploadToSlate(file);
setImages([
...images,
{
isUploading: false,
url: `https://slate.textile.io/ipfs/${result.data.cid}`,
},
]);
setCurrentImage(`https://slate.textile.io/ipfs/${result.data.cid}`);
console.log("uploaded");
} catch (e) {
console.log(e);
}
};
const handleCurrentImage = (e) => {
e.preventDefault();
setCurrentImage(e.target.src);
};
const handleInputChange = (e, setter) => {
e.preventDefault();
setter(e.target.value);
};
const handleClaimSubmit = async (e) => {
e.preventDefault();
let imageUrls = images.map((image) => {
return image.url;
});
let claimObj = {
images: imageUrls,
claimTitle,
claimSummary,
dateOfIncident,
claimAmount: claimableAmount,
author: signerAddress,
};
console.log(claimObj);
// tried using fleek instead of threadDB.
// let response = await fleekStorage.upload({
// apiKey: "3aFyv9UlnpyVvuhdoy+WMA==",
// apiSecret: "vUREhYRSH5DP8WehKP+N8jTLoOJUBw+RA9TPLUKneK8=",
// key: uuidv4(),
// data: JSON.stringify(claimObj),
// });
// adding claim data to threadDB.
let response = await addToThread(
textileClient,
"bafkyspsyykcninhqn4ht6d6jeqmzq4cepy344akmkhjk75dmw36wq4q",
"claimsData",
claimObj
);
// create proposal on contract basically store the hash.
createProposal(
claimTitle,
(new Date(dateOfIncident).getTime() / 1000).toString(),
response.hash
);
};
return (
<Grid
paddingBottom='20px'
pt='20px'
height='100%'
px='250px'
width='100%'
templateColumns='2fr 1fr'
gridGap={5}
alignItems='flex-start'>
<VStack width='100%' alignItems='flex-start'>
<Skeleton isLoaded={!isPageLoading}>
<Heading as='h4' fontSize='28px'>
Make a Claim
</Heading>
</Skeleton>
<form style={{ width: "100%" }}>
<VStack width='100%' spacing={5} alignItems='flex-start'>
<input
multiple
onChange={(e) => handleImage(e)}
type='file'
style={{ display: "none" }}
id='image-input'
accept='image/*'
/>
{images.length == 0 ? (
isPageLoading ? (
<Spinner
colorScheme='whatsapp'
color='whatsapp.500'
alignSelf='center'
/>
) : (
<Box
cursor='pointer'
as='label'
htmlFor='image-input'
px='35px'
width='100%'
borderRadius='10px'
height='70px'
borderWidth='1px'
borderStyle='solid'
borderColor='whatsapp.500'>
<VStack
height='100%'
width='100%'
justifyContent='center'>
<TiPlus style={{ fill: "#22C35E" }} />
<Text fontWeight='600' color='#22C35E'>
Image
</Text>
</VStack>
</Box>
)
) : (
<>
<Box
mt='10px !important'
boxShadow='lg'
borderRadius='10px'>
<Image
borderRadius='10px'
src={currentImage}
/>
</Box>
<HStack width='100%' overflowX='scroll'>
{images.map((image, index) => {
return image.isUploading ? (
<Spinner key={index} />
) : (
<Image
key={image.url}
onClick={(e) => {
handleCurrentImage(e);
}}
borderRadius='10px'
height='70px'
src={image.url}
/>
);
})}
<Box
cursor='pointer'
as='label'
htmlFor='image-input'
px='35px'
borderRadius='10px'
height='70px'
borderWidth='1px'
borderStyle='solid'
borderColor='whatsapp.500'>
<VStack
height='100%'
width='100%'
justifyContent='center'>
<TiPlus
style={{ fill: "#22C35E" }}
/>
<Text
fontWeight='600'
color='#22C35E'>
Image
</Text>
</VStack>
</Box>
</HStack>
</>
)}
<VStack spacing={5} width='100%'>
<FormControl isRequired>
<Skeleton isLoaded={!isPageLoading}>
<FormLabel>Claim Title</FormLabel>
</Skeleton>
<Skeleton isLoaded={!isPageLoading}>
<Input
onChange={(e) =>
handleInputChange(e, setClaimTitle)
}
/>
</Skeleton>
</FormControl>
<FormControl isRequired>
<Skeleton isLoaded={!isPageLoading}>
<FormLabel>Summary of Incident</FormLabel>
</Skeleton>
<Skeleton isLoaded={!isPageLoading}>
<Textarea
onChange={(e) =>
handleInputChange(
e,
setClaimSummary
)
}
row='10'
/>
</Skeleton>
<Skeleton isLoaded={!isPageLoading}>
<FormHelperText>
Try to precise
</FormHelperText>
</Skeleton>
</FormControl>
<VStack width='100%'>
<HStack width='100%'>
<FormControl isRequired>
<Skeleton isLoaded={!isPageLoading}>
<FormLabel>
Date of Incident
</FormLabel>
</Skeleton>
<Skeleton isLoaded={!isPageLoading}>
<Input
onChange={(e) =>
handleInputChange(
e,
setDateOfIncident
)
}
type='date'
/>
</Skeleton>
</FormControl>
</HStack>
</VStack>
<Button
onClick={(e) => handleClaimSubmit(e)}
isLoading={isPageLoading}
mt='30px !important'
width='100%'
textTransform='uppercase'
type='submit'
colorScheme='whatsapp'>
Submit Claim
</Button>
</VStack>
</VStack>
</form>
</VStack>
<VStack width='100%'>
<Card isLoading={isPageLoading} cardTitle='Claimable Amount'>
<Skeleton isLoaded={!isPageLoading}>
<Heading
textColor='whatsapp.500'
fontSize='24px'
as='h3'>
{parseFloat(claimableAmount).toFixed(6)} DAI
</Heading>
</Skeleton>
</Card>
</VStack>
</Grid>
);
}
Example #14
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 #15
Source File: sidebar.js From idena-web with MIT License | 4 votes |
function ActionPanel({onClose}) {
const {t} = useTranslation()
const router = useRouter()
const epoch = useEpoch()
const [identity] = useIdentity()
const onboardingPopoverPlacement = useBreakpointValue(['top', 'right'])
const [
currentOnboarding,
{showCurrentTask, dismissCurrentTask},
] = useOnboarding()
useEffect(() => {
if (
eitherState(
currentOnboarding,
onboardingShowingStep(OnboardingStep.StartTraining),
onboardingShowingStep(OnboardingStep.ActivateInvite)
)
)
onClose()
}, [currentOnboarding, onClose])
if (!epoch) {
return (
<Stack spacing={[2, '1px']} mt={6}>
<Block
title={t('My current task')}
roundedTop="md"
roundedBottom={['md', 'none']}
>
<Skeleton
h={[4, '13px']}
mt={[1, '3.5px']}
mb={[1, '3px']}
borderRadius="sm"
startColor="#72767A"
endColor="#6A6E72"
/>
</Block>
<Block
title={t('Next validation')}
roundedBottom="md"
roundedTop={['md', 'none']}
>
<Skeleton
h={[4, '13px']}
mt={[1, '3.5px']}
mb={[1, '3px']}
borderRadius="sm"
startColor="#72767A"
endColor="#6A6E72"
/>
</Block>
</Stack>
)
}
const eitherOnboardingState = (...states) =>
eitherState(currentOnboarding, ...states)
const {currentPeriod, nextValidation} = epoch
const isPromotingNextOnboardingStep =
currentPeriod === EpochPeriod.None &&
(eitherOnboardingState(
onboardingPromotingStep(OnboardingStep.StartTraining),
onboardingPromotingStep(OnboardingStep.ActivateInvite),
onboardingPromotingStep(OnboardingStep.ActivateMining)
) ||
(eitherOnboardingState(
onboardingPromotingStep(OnboardingStep.Validate)
) &&
[IdentityStatus.Candidate, IdentityStatus.Newbie].includes(
identity.state
)) ||
(eitherOnboardingState(
onboardingPromotingStep(OnboardingStep.CreateFlips)
) &&
[IdentityStatus.Newbie].includes(identity.state)))
return (
<Stack spacing={[2, '1px']} mt={6}>
{currentPeriod !== EpochPeriod.None && (
<Block
title={t('Current period')}
roundedTop="md"
roundedBottom={['md', 'none']}
>
{currentPeriod}
</Block>
)}
<ChakraBox
cursor={isPromotingNextOnboardingStep ? 'pointer' : 'default'}
onClick={() => {
if (
eitherOnboardingState(
OnboardingStep.StartTraining,
OnboardingStep.ActivateInvite,
OnboardingStep.ActivateMining
)
)
router.push('/home')
if (eitherOnboardingState(OnboardingStep.CreateFlips))
router.push('/flips/list')
showCurrentTask()
}}
>
<PulseFrame
isActive={isPromotingNextOnboardingStep}
roundedTop={[
'md',
currentPeriod === EpochPeriod.None ? 'md' : 'none',
]}
roundedBottom={[
'md',
currentPeriod !== EpochPeriod.None ? 'md' : 'none',
]}
>
<Block
title={t('My current task')}
roundedTop={[
'md',
currentPeriod === EpochPeriod.None ? 'md' : 'none',
]}
roundedBottom={[
'md',
currentPeriod !== EpochPeriod.None ? 'md' : 'none',
]}
>
<CurrentTask
epoch={epoch.epoch}
period={currentPeriod}
identity={identity}
/>
</Block>
</PulseFrame>
</ChakraBox>
{currentPeriod === EpochPeriod.None && (
<OnboardingPopover
isOpen={eitherOnboardingState(
onboardingShowingStep(OnboardingStep.Validate)
)}
placement={onboardingPopoverPlacement}
>
<PopoverTrigger>
<ChakraBox
bg={
eitherOnboardingState(
onboardingShowingStep(OnboardingStep.Validate)
)
? 'rgba(216, 216, 216, .1)'
: 'transparent'
}
position="relative"
zIndex="docked"
>
<Block
title={t('Next validation')}
roundedBottom="md"
roundedTop={['md', 'none']}
>
{formatValidationDate(nextValidation)}
<Menu autoSelect={false} mr={1}>
<MenuButton
rounded="md"
_hover={{bg: 'unset'}}
_expanded={{bg: 'brandGray.500'}}
_focus={{outline: 0}}
position="absolute"
top={1}
right={1}
py={1.5}
px={1 / 2}
>
<MoreIcon boxSize={5} />
</MenuButton>
<MenuList
placement="bottom-end"
border="none"
shadow="0 4px 6px 0 rgba(83, 86, 92, 0.24), 0 0 2px 0 rgba(83, 86, 92, 0.2)"
rounded="lg"
py={2}
minWidth="145px"
>
<MenuItem
color="brandGray.500"
fontWeight={500}
px={3}
py={2}
_hover={{bg: 'gray.50'}}
_focus={{bg: 'gray.50'}}
_selected={{bg: 'gray.50'}}
_active={{bg: 'gray.50'}}
onClick={() => {
openExternalUrl(
buildNextValidationCalendarLink(nextValidation)
)
}}
>
<PlusSquareIcon
boxSize={5}
mr={3}
color="brandBlue.500"
/>
Add to calendar
</MenuItem>
</MenuList>
</Menu>
</Block>
</ChakraBox>
</PopoverTrigger>
<Portal>
<OnboardingPopoverContent
display={
eitherOnboardingState(
onboardingShowingStep(OnboardingStep.Validate)
)
? 'flex'
: 'none'
}
title={t('Schedule your next validation')}
maxW="sm"
additionFooterActions={
<Button
variant="unstyled"
onClick={() => {
openExternalUrl(
'https://medium.com/idena/how-do-i-start-using-idena-c49418e01a06'
)
}}
>
{t('Read more')}
</Button>
}
onDismiss={dismissCurrentTask}
>
<Stack spacing={5}>
<OnboardingPopoverContentIconRow
icon={<TelegramIcon boxSize={6} />}
>
<Trans i18nKey="onboardingValidateSubscribe" t={t}>
<OnboardingLinkButton href="https://t.me/IdenaAnnouncements">
Subscribe
</OnboardingLinkButton>{' '}
to the Idena Announcements (important updates only)
</Trans>
</OnboardingPopoverContentIconRow>
<OnboardingPopoverContentIconRow
icon={<SyncIcon boxSize={5} />}
>
{t(
`Sign in into your account 15 mins before the validation starts.`
)}
</OnboardingPopoverContentIconRow>
<OnboardingPopoverContentIconRow
icon={<TimerIcon boxSize={5} />}
>
{t(
`Solve the flips quickly when validation starts. The first 6 flips must be submitted in less than 2 minutes.`
)}
</OnboardingPopoverContentIconRow>
<OnboardingPopoverContentIconRow
icon={<GalleryIcon boxSize={5} />}
>
<Trans i18nKey="onboardingValidateTest" t={t}>
<OnboardingLinkButton
onClick={() => {
dismissCurrentTask()
router.push('/try')
}}
>
Test yourself
</OnboardingLinkButton>{' '}
before the validation
</Trans>
</OnboardingPopoverContentIconRow>
</Stack>
</OnboardingPopoverContent>
</Portal>
</OnboardingPopover>
)}
</Stack>
)
}