@chakra-ui/react#Spinner JavaScript Examples

The following examples show how to use @chakra-ui/react#Spinner. 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: invite.js    From idena-web with MIT License 6 votes vote down vote up
export default function DnaInvitePage() {
  useDnaInviteRedirect()

  return (
    <Layout canRedirect={false}>
      <Spinner />
    </Layout>
  )
}
Example #2
Source File: vote.js    From idena-web with MIT License 6 votes vote down vote up
export default function DnaVotePage() {
  useDnaVoteRedirect()

  return (
    <Layout canRedirect={false}>
      <Spinner />
    </Layout>
  )
}
Example #3
Source File: Messages.jsx    From realtime-chat-supabase-react with Apache License 2.0 6 votes vote down vote up
export default function Messages() {
  const { username, loadingInitial, error, getMessagesAndSubscribe, messages } =
    useAppContext();
  const reversed = [...messages].reverse();
  if (loadingInitial)
    return (
      <Box textAlign="center">
        <Spinner />
      </Box>
    );
  if (error)
    return (
      <Alert status="error" mt="20px">
        {error}
        <Button
          ml="5px"
          onClick={getMessagesAndSubscribe}
          colorScheme="red"
          variant="link"
        >
          try to reconnect
        </Button>
      </Alert>
    );

  if (!messages.length)
    return (
      <Box as="h3" textAlign="center">
        No messages ?
      </Box>
    );

  return reversed.map((message) => {
    const isYou = message.username === username;
    return <Message key={message.id} message={message} isYou={isYou} />;
  });
}
Example #4
Source File: signin.js    From idena-web with MIT License 5 votes vote down vote up
export default function SigninPage() {
  const {t} = useTranslation()

  const failToast = useFailToast()

  const {onOpen, ...dnaSignInDisclosure} = useDisclosure()

  const {
    params: {
      nonce_endpoint: nonceEndpoint,
      authentication_endpoint: authenticationEndpoint,
      favicon_url: faviconUrl,
      ...dnaSignInParams
    },
  } = useDnaLinkMethod(DnaLinkMethod.SignIn, {
    onReceive: onOpen,
  })

  const [, {dismiss: dimissDnaAppLink}] = useDnaAppLink()

  return (
    <Layout canRedirect={false}>
      <Page>
        <PageTitle>{t('Sign in with Idena')}</PageTitle>
        <Box>
          <Spinner />
          {Boolean(authenticationEndpoint) && (
            <DnaSignInDialog
              authenticationEndpoint={authenticationEndpoint}
              nonceEndpoint={nonceEndpoint}
              faviconUrl={faviconUrl}
              {...dnaSignInParams}
              {...dnaSignInDisclosure}
              onCompleteSignIn={dimissDnaAppLink}
              onSignInError={failToast}
            />
          )}
        </Box>
      </Page>
    </Layout>
  )
}
Example #5
Source File: Loading.js    From web-client with Apache License 2.0 5 votes vote down vote up
export default function Loading() {
    return <figure className='message__container'>
        <Spinner />
        Loading...
    </figure>
}
Example #6
Source File: InformationCards.js    From DAOInsure with MIT License 4 votes vote down vote up
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: ActivityPage.js    From DAOInsure with MIT License 4 votes vote down vote up
function ActivityPage() {
	const [data, setData] = useState();

	const [loadingData, setLoadingData] = useState();
	useEffect(() => {
		async function init() {
			setLoadingData(true);
			// querying superfluid subgraph to create pie diagram of flow towards DAO Contract
			const response = await axios.post(
				"https://api.thegraph.com/subgraphs/name/superfluid-finance/superfluid-mumbai",
				{
					query: `
                    {
                        flows(where:{ recipient: "0xb77963bfd55f5246068c09a2048fa3ab310e4a17" }) {
                        id
                        flowRate
                        lastUpdate
                            owner {
                                id
                            }
                        }
                    }
                `,
				}
			);

			let datas = [];

			response.data.data.flows.map((flow) => {
				let secondsElapsed =
					Math.floor(Date.now() / 1000) - parseInt(flow.lastUpdate);
				let outFlowed = web3.utils.fromWei(
					web3.utils
						.toBN(flow.flowRate)
						.mul(web3.utils.toBN(secondsElapsed))
						.toString(),
					"ether"
				);
				let obj = {
					id: flow.owner.id,
					label: flow.owner.id,
					value: outFlowed,
					flowRate: web3.utils.toBN(flow.flowRate),
					sumInWei: web3.utils
						.toBN(flow.flowRate)
						.mul(web3.utils.toBN(secondsElapsed)),
				};
				datas.push(obj);
			});
			setData(datas);
			setLoadingData(false);
		}
		init();
	}, [data]);

	useEffect(() => {
		if (data != undefined) {
			setTimeout(() => {
				for (let i = 0; i < data.length; i++) {
					data[i].value = web3.utils
						.fromWei(data[i].sumInWei.add(data[i].flowRate))
						.toString();
					data[i].sumInWei = data[i].sumInWei.add(data[i].flowRate);
				}
				setData(data);
			}, 1000);
		}
	}, [data]);

	return (
		<Grid px='250px' gridGap='10px' py='20px'>
			<Heading fontSize='24px' color='whatsapp.500'>
				Members
			</Heading>
			<Box height='400px'>
				{loadingData ? <Spinner /> : <MyResponsivePie data={data} />}
			</Box>
			<Table>
				<Thead>
					<Tr>
						<Th>Address</Th>
						<Th>outFlowed</Th>
					</Tr>
				</Thead>
				<Tbody>
					{data == undefined ? (
						<Spinner />
					) : (
						<>
							{data.map((data, index) => {
								return (
									<Tr>
										<Td>
											<GreenTag>{data.id}</GreenTag>
										</Td>
										<Td>{data.value}</Td>
									</Tr>
								);
							})}
						</>
					)}
				</Tbody>
			</Table>
		</Grid>
	);
}
Example #8
Source File: MakeClaim.js    From DAOInsure with MIT License 4 votes vote down vote up
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 #9
Source File: VotingPage.js    From DAOInsure with MIT License 4 votes vote down vote up
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 #10
Source File: Player.jsx    From bottle-radio with MIT License 4 votes vote down vote up
Player = () => {
  const variables = window._env_ ? window._env_ : { REACT_ICECAST_URL: "" };
  const [playing, setPlaying] = useState(false);
  const [loading, setLoading] = useState(false);
  const [muted, setMuted] = useState(false);
  const [firstLoad, setFirstLoad] = useState(true);
  const [nowPlaying, setNowPlaying] = useState(["No data", "No data"]);
  const [listeners, setListeners] = useState([0, 0]);
  const { colorMode } = useColorMode();
  const colorHover = { light: "white", dark: "black" };
  const { isOpen, onOpen, onClose } = useDisclosure();
  const trackLinks = useSaveTrack(
    nowPlaying[0],
    nowPlaying[1]
  );
  const audioRef = useRef(null);
  const { setPlayer } = useContext(VisualiserContext);

  useEffect(() => {
    const audio = document.getElementById("player");
    if (audio) {
      setPlayer(audioRef);
    }
  }, [setPlayer]);

  useEffect(() => {
    const updateStats = async () => {
      let url = variables.REACT_ICECAST_URL + "status-json.xsl";
      let response = await fetch(url);
      let json = await response.json();
      let track = json.icestats.source.title;
      if (track && track !== "") {
        let artist = track.split(" - ")[0];
        track = track.split(" - ").slice(1).join(" - ");
        setNowPlaying([track, artist]);
      }
      let listeners = json.icestats.source.listeners;
      let peakListeners = json.icestats.source.listener_peak;

      if (listeners && listeners) {
        setListeners([listeners, peakListeners]);
      }
    };
    updateStats();
    setInterval(() => {
      updateStats();
    }, 10000);
  }, [variables.REACT_ICECAST_URL]);

  const togglePlay = () => {
    let player = document.getElementById("player");
    if (firstLoad) {
      setFirstLoad(false);
    }
    if (player.paused) {
      setPlaying(true);
      player.load();
      player.play();
    } else {
      setPlaying(false);
      player.pause();
    }
  };

  const changeVolume = (value) => {
    let player = document.getElementById("player");
    value <= 0 ? setMuted(true) : setMuted(false);
    player.volume = value / 100;
  };

  const TrackModal = (props) => {
    const { modal, setModal } = useContext(ModalContext);

    useEffect(() => {
      if (!modal) {
        setModal(trackLinks);
      }
    }, [modal, setModal]);

    return (
      <div>
        <Modal
          isOpen={isOpen}
          onClose={() => {
            onClose();
            setModal();
          }}
          size="sm"
          isCentered
        >
          <ModalOverlay>
            <ModalContent>
              <ModalCloseButton />
              <ModalBody>
                <Grid templateColumns="1fr 1fr" justifyItems="center" gap={0}>
                  {modal && modal.length > 0 ? (
                    modal.map((link) => (
                      <Link key={link.url} href={link.url} isExternal>
                        <Button variant="ghost">{link.displayName}</Button>
                      </Link>
                    ))
                  ) : (
                    <div>
                      <Spinner size="sm" /> Loading...
                    </div>
                  )}
                </Grid>
              </ModalBody>
            </ModalContent>
          </ModalOverlay>
        </Modal>
      </div>
    );
  };

  return (
    <div>
      <Flex
        direction="column"
        justify="center"
        align="center"
        width="100%"
        height="100%"
      >
        <Box>
          <Grid
            m={2}
            p={2}
            templateColumns="auto 1fr auto"
            alignItems="center"
            gap={1}
          >
            <Box
              gridRow="1/4"
              w="80px"
              h="80px"
              aria-label="Play toggle"
              as={loading ? FaSpinner : playing ? FaPauseCircle : FaPlayCircle}
              onClick={togglePlay}
              _hover={{ color: colorHover[colorMode] }}
              mr={1}
              className={loading ? "icon-spin" : ""}
            />
            <Text m={0} align="center">
              <strong>{nowPlaying[0]}</strong>
            </Text>
            <Text m={0} align="center">
              {nowPlaying[1]}
            </Text>

            <Flex direction="row" justify="center" maxWidth={400} p={2}>
              <Slider
                defaultValue={100}
                min={0}
                max={100}
                step={10}
                onChange={changeVolume}
                width="80px"
              >
                <SliderTrack>
                  <SliderFilledTrack bg="tomato" />
                </SliderTrack>
                <SliderThumb size={2} />
              </Slider>
              <Box
                w="20px"
                h="20px"
                as={muted ? FaVolumeMute : FaVolumeUp}
                ml={3}
              />
              <audio
                id="player"
                crossOrigin="anonymous"
                autoPlay
                preload="none"
                ref={audioRef}
                onPlay={() => setPlaying(true)}
                onPause={() => setPlaying(false)}
                onLoadStart={() => {
                  if (!firstLoad) {
                    setLoading(true);
                  }
                }}
                onCanPlay={() => setLoading(false)}
              >
                <source
                  src={variables.REACT_ICECAST_URL + "radio.mp3"}
                  type="audio/mp3"
                />
                Your browser does not support the audio element.
              </audio>
            </Flex>
            <Text gridColumn="1/4">
              <strong>Listeners: </strong>
              {listeners[0]} <strong>Peak: </strong>
              {listeners[1]}
            </Text>
            <Box gridColumn="3" gridRow="1/4" alignItems="center">
              <Box
                w="25px"
                h="25px"
                as={FaHeart}
                mx={1}
                onClick={onOpen}
                _hover={{ color: "tomato" }}
              />
              {isOpen ? <TrackModal /> : null}
            </Box>
          </Grid>
        </Box>
      </Flex>
    </div>
  );
}
Example #11
Source File: raw.js    From idena-web with MIT License 4 votes vote down vote up
export default function DnaRawPage() {
  const {t} = useTranslation()

  const failToast = useFailToast()

  const handleInvalidDnaLink = React.useCallback(() => {
    failToast({
      title: t('Invalid DNA link'),
      description: t(`You must provide valid URL including protocol version`),
    })
  }, [failToast, t])

  const dnaRawTxDisclosure = useDisclosure()

  const {params: dnaRawTxParams} = useDnaLinkMethod(DnaLinkMethod.RawTx, {
    onReceive: dnaRawTxDisclosure.onOpen,
    onInvalidLink: handleInvalidDnaLink,
  })

  const dnaSendSucceededDisclosure = useDisclosure()

  const dnaSendFailedDisclosure = useDisclosure()

  const [dnaSendResponse, setDnaSendResponse] = React.useState()

  const {coinbase} = useAuthState()

  const {
    data: {balance},
  } = useQuery(['get-balance', coinbase], () => fetchBalance(coinbase), {
    initialData: {balance: 0},
    enabled: !!coinbase,
  })

  const [, {dismiss: dismissDnaAppLink}] = useDnaAppLink()

  return (
    <Layout canRedirect={false}>
      <Page>
        <PageTitle>{t('Send raw transaction')}</PageTitle>
        <Box>
          <Spinner />
          <DnaRawDialog
            balance={balance}
            {...dnaRawTxParams}
            {...dnaRawTxDisclosure}
            onSendSuccess={({hash, url}) => {
              dnaRawTxDisclosure.onClose()
              setDnaSendResponse({hash, url})
              dnaSendSucceededDisclosure.onOpen()
            }}
            onSendError={({error, url}) => {
              dnaRawTxDisclosure.onClose()
              setDnaSendResponse({error, url})
              dnaSendFailedDisclosure.onOpen()
            }}
            onSendRawTxFailed={failToast}
            onCompleteSend={dismissDnaAppLink}
          />

          <DnaSendSucceededDialog
            {...dnaSendResponse}
            {...dnaSendSucceededDisclosure}
            onCompleteSend={() => {
              dismissDnaAppLink()
              dnaSendSucceededDisclosure.onClose()
            }}
          />

          <DnaSendFailedDialog
            onRetrySucceeded={({hash, url}) => {
              setDnaSendResponse({hash, url})
              dnaSendFailedDisclosure.onClose()
              dnaSendSucceededDisclosure.onOpen()
            }}
            onRetryFailed={({error, url}) => {
              setDnaSendResponse({error, url})
            }}
            {...dnaSendResponse}
            {...dnaSendFailedDisclosure}
            onOpenFailUrl={() => {
              dismissDnaAppLink()
              dnaSendFailedDisclosure.onClose()
            }}
          />
        </Box>
      </Page>
    </Layout>
  )
}
Example #12
Source File: send.js    From idena-web with MIT License 4 votes vote down vote up
export default function DnaSendPage() {
  const {t} = useTranslation()

  const failToast = useFailToast()

  const handleInvalidDnaLink = React.useCallback(() => {
    failToast({
      title: t('Invalid DNA link'),
      description: t(`You must provide valid URL including protocol version`),
    })
  }, [failToast, t])

  const dnaSendDisclosure = useDisclosure()

  const {params: dnaSendParams} = useDnaLinkMethod(DnaLinkMethod.Send, {
    onReceive: dnaSendDisclosure.onOpen,
    onInvalidLink: handleInvalidDnaLink,
  })

  const dnaSendSucceededDisclosure = useDisclosure()

  const dnaSendFailedDisclosure = useDisclosure()

  const [dnaSendResponse, setDnaSendResponse] = React.useState()

  const {coinbase} = useAuthState()

  const {
    data: {balance},
  } = useQuery(['get-balance', coinbase], () => fetchBalance(coinbase), {
    initialData: {balance: 0},
    enabled: !!coinbase,
  })

  const [, {dismiss: dismissDnaAppLink}] = useDnaAppLink()

  return (
    <Layout canRedirect={false}>
      <Page>
        <PageTitle>{t('Send iDNA')}</PageTitle>
        <Box>
          <Spinner />
          <DnaSendDialog
            balance={balance}
            {...dnaSendParams}
            {...dnaSendDisclosure}
            onDepositSuccess={({hash, url}) => {
              dnaSendDisclosure.onClose()
              setDnaSendResponse({hash, url})
              dnaSendSucceededDisclosure.onOpen()
            }}
            onDepositError={({error, url}) => {
              dnaSendDisclosure.onClose()
              setDnaSendResponse({error, url})
              dnaSendFailedDisclosure.onOpen()
            }}
            onSendTxFailed={failToast}
            onCompleteSend={dismissDnaAppLink}
          />

          <DnaSendSucceededDialog
            {...dnaSendResponse}
            {...dnaSendSucceededDisclosure}
            onCompleteSend={() => {
              dismissDnaAppLink()
              dnaSendSucceededDisclosure.onClose()
            }}
          />

          <DnaSendFailedDialog
            onRetrySucceeded={({hash, url}) => {
              setDnaSendResponse({hash, url})
              dnaSendFailedDisclosure.onClose()
              dnaSendSucceededDisclosure.onOpen()
            }}
            onRetryFailed={({error, url}) => {
              setDnaSendResponse({error, url})
            }}
            {...dnaSendResponse}
            {...dnaSendFailedDisclosure}
            onOpenFailUrl={() => {
              dismissDnaAppLink()
              dnaSendFailedDisclosure.onClose()
            }}
          />
        </Box>
      </Page>
    </Layout>
  )
}
Example #13
Source File: image-search.js    From idena-web with MIT License 4 votes vote down vote up
export function ImageSearchDialog({onPick, onClose, onError, ...props}) {
  const {t} = useTranslation()

  const searchInputRef = React.useRef()

  const [current, send] = useMachine(
    Machine({
      context: {
        images: [],
      },
      initial: 'idle',
      states: {
        idle: {},
        searching: {
          invoke: {
            // eslint-disable-next-line no-shadow
            src: (_, {query}) => searchImages(query),
            onDone: {
              target: 'done',
              actions: [
                assign({
                  images: (_, {data}) => data,
                }),
                log(),
              ],
            },
            onError: 'fail',
          },
        },
        done: {
          on: {
            PICK: {
              actions: [
                assign({
                  selectedImage: (_, {image}) => image,
                }),
                log(),
              ],
            },
          },
        },
        fail: {
          entry: [(_, {data: {message}}) => onError(message), log()],
        },
      },
      on: {
        SEARCH: 'searching',
      },
    })
  )

  const {images, selectedImage} = current.context
  const [query, setQuery] = useState()

  return (
    <Dialog
      size="lg"
      initialFocusRef={searchInputRef}
      onClose={onClose}
      {...props}
    >
      <DialogBody d="flex">
        <Stack minH="sm" maxH="sm" spacing={4} flex={1}>
          <Stack
            isInline
            as="form"
            onSubmit={e => {
              e.preventDefault()
              send('SEARCH', {query})
            }}
          >
            <InputGroup w="full">
              <InputLeftElement w={5} h={5} top={1.5} left={3}>
                <SearchIcon boxSize={3} color="gray.200" />
              </InputLeftElement>
              <Input
                ref={searchInputRef}
                type="search"
                id="query"
                placeholder={t('Search the picture on the web')}
                bg="gray.50"
                pl={10}
                value={query}
                onChange={e => setQuery(e.target.value)}
              />
            </InputGroup>
            <PrimaryButton type="submit">Search</PrimaryButton>
          </Stack>
          {eitherState(current, 'idle') && (
            <Flex direction="column" flex={1} align="center" justify="center">
              <Stack spacing={4} align="center" w="3xs">
                <Box p={3}>
                  <SearchIcon boxSize="56px" color="gray.100" />
                </Box>
                <Text color="muted" textAlign="center" w="full">
                  {t(
                    'Type your search in the box above to find images using search box'
                  )}
                </Text>
              </Stack>
            </Flex>
          )}
          {eitherState(current, 'done') && (
            <SimpleGrid
              columns={4}
              spacing={2}
              overflow="auto"
              px={6}
              style={{marginLeft: '-24px', marginRight: '-24px'}}
            >
              {images.map(({thumbnail}) => (
                <AspectRatio
                  ratio={1}
                  w={28}
                  minH={28}
                  bg={thumbnail === selectedImage ? 'blue.032' : 'white'}
                  borderColor={
                    thumbnail === selectedImage ? 'blue.500' : 'gray.50'
                  }
                  borderWidth={1}
                  borderRadius="md"
                  overflow="hidden"
                  position="relative"
                  transition="all 0.6s cubic-bezier(0.16, 1, 0.3, 1)"
                  onClick={() => {
                    send('PICK', {image: thumbnail})
                  }}
                  onDoubleClick={() => {
                    onPick(selectedImage)
                  }}
                >
                  <Image
                    src={thumbnail}
                    objectFit="contain"
                    objectPosition="center"
                    borderColor={
                      thumbnail === selectedImage ? 'blue.500' : 'transparent'
                    }
                    borderWidth={1}
                    borderRadius="md"
                  />
                </AspectRatio>
              ))}
            </SimpleGrid>
          )}
          {eitherState(current, 'searching') && (
            <Flex direction="column" flex={1} align="center" justify="center">
              <Spinner color="blue.500" />
            </Flex>
          )}
        </Stack>
      </DialogBody>
      <DialogFooter>
        <SecondaryButton onClick={onClose}>{t('Cancel')}</SecondaryButton>
        <PrimaryButton
          onClick={() => {
            onPick(selectedImage)
          }}
        >
          {t('Select')}
        </PrimaryButton>
      </DialogFooter>
    </Dialog>
  )
}
Example #14
Source File: Blob.js    From blobs.app with MIT License 4 votes vote down vote up
Blob = ({
  size,
  isOutline,
  type,
  svgPath,
  color,
  colors,
  image,
  pattern,
}) => {
  const ref = useRef(null);
  const [imgLoaded, setImgLoaded] = useState(false);
  const pattenBgColor = useColorModeValue('#d1d8e0', '#6c7c93');

  const props = {
    fill: color,
  };
  if (type === 'gradient') {
    props.fill = 'url(#gradient)';
  }
  if (isOutline) {
    props.strokeWidth = '7px';
    props.fill = 'none';
    props.stroke = color;
  }
  if (type === 'gradient' && isOutline) {
    props.stroke = 'url(#gradient)';
  }
  if (!svgPath) {
    return (
      <Flex justify="center" alignItems="center" h="100%">
        <Spinner />
      </Flex>
    );
  }

  return (
    <svg
      viewBox={`0 0 ${size} ${size}`}
      xmlns="http://www.w3.org/2000/svg"
      xmlnsXlink="http://www.w3.org/1999/xlink"
      width="100%"
      id="blobSvg"
      ref={ref}
    >
      {type === 'solid' && <path id="blob" d={svgPath} {...props} />}
      {type === 'gradient' && (
        <>
          <defs>
            <linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
              <stop offset="0%" style={{ stopColor: colors[0] }} />
              <stop offset="100%" style={{ stopColor: colors[1] }} />
            </linearGradient>
          </defs>
          <path id="blob" d={svgPath} {...props} />
        </>
      )}
      {type === 'pattern' && (
        <>
          <defs>
            <pattern
              id="pattern"
              x="0"
              y="0"
              width={Patterns[pattern].width}
              height={Patterns[pattern].height}
              patternUnits="userSpaceOnUse"
              fill={pattenBgColor}
            >
              <path d={Patterns[pattern].path} />
            </pattern>
          </defs>
          <path id="blob" d={svgPath} {...props} fill="url(#pattern)" />
        </>
      )}

      {type === 'image' && (
        <>
          <defs>
            <clipPath id="shape">
              <path id="blob" d={svgPath} {...props} />
            </clipPath>
          </defs>
          {!imgLoaded && (
            <image
              x="0"
              y="0"
              width="100%"
              height="100%"
              clipPath="url(#shape)"
              xlinkHref={LoadingImg}
              preserveAspectRatio="none"
            />
          )}
          <image
            x="0"
            y="0"
            width="100%"
            height="100%"
            clipPath="url(#shape)"
            xlinkHref={image}
            preserveAspectRatio="none"
            onLoad={() => {
              setImgLoaded(true);
            }}
          />
        </>
      )}
    </svg>
  );
}
Example #15
Source File: Account.jsx    From scaffold-directory with MIT License 4 votes vote down vote up
/*
  ~ What it does? ~

  Displays an Address, Balance, and Wallet as one Account component,
  also allows users to log in to existing accounts and log out

  ~ How can I use? ~

  <Account
    address={address}
    localProvider={localProvider}
    userProvider={userProvider}
    mainnetProvider={mainnetProvider}
    price={price}
    web3Modal={web3Modal}
    loadWeb3Modal={loadWeb3Modal}
    logoutOfWeb3Modal={logoutOfWeb3Modal}
    blockExplorer={blockExplorer}
  />

  ~ Features ~

  - Provide address={address} and get balance corresponding to the given address
  - Provide localProvider={localProvider} to access balance on local network
  - Provide userProvider={userProvider} to display a wallet
  - Provide mainnetProvider={mainnetProvider} and your address will be replaced by ENS name
              (ex. "0xa870" => "user.eth")
  - Provide price={price} of ether and get your balance converted to dollars
  - Provide web3Modal={web3Modal}, loadWeb3Modal={loadWeb3Modal}, logoutOfWeb3Modal={logoutOfWeb3Modal}
              to be able to log in/log out to/from existing accounts
  - Provide blockExplorer={blockExplorer}, click on address and get the link
              (ex. by default "https://etherscan.io/" or for xdai "https://blockscout.com/poa/xdai/")
*/

export default function Account({
  address,
  connectText,
  ensProvider,
  isWalletConnected,
  loadWeb3Modal,
  logoutOfWeb3Modal,
  setUserRole,
  userProvider,
  userRole,
}) {
  const ens = useDisplayAddress(ensProvider, address);
  const shortAddress = ellipsizedAddress(address);
  const toast = useToast({ position: "top", isClosable: true });
  const [isPopoverOpen, setIsPopoverOpen] = useState(true);
  const registerButtonRef = useRef();
  const openPopover = () => setIsPopoverOpen(true);
  const closePopover = () => setIsPopoverOpen(false);
  const { primaryFontColor, secondaryFontColor, dividerColor } = useCustomColorModes();

  if (!userRole && isWalletConnected) {
    return <Spinner />;
  }

  const hasEns = ens !== shortAddress;
  const isAdmin = userRole === USER_ROLES.admin;
  const isBuilder = userRole === USER_ROLES.builder;
  const isAnonymous = userRole === USER_ROLES.anonymous;

  const connectWallet = (
    <Button colorScheme="blue" key="loginbutton" onClick={loadWeb3Modal}>
      {connectText || "connect"}
    </Button>
  );

  const UserDisplayName = ({ mb, textAlign }) =>
    hasEns ? (
      <>
        <Text fontSize="md" fontWeight="bold" textAlign={textAlign} color={primaryFontColor}>
          {ens}
        </Text>
        <Text color={secondaryFontColor} fontSize="sm" fontWeight="normal" textAlign={textAlign} mb={mb}>
          {shortAddress}
        </Text>
      </>
    ) : (
      <Text fontSize="md" fontWeight="semibold" textAlign={textAlign} color={primaryFontColor} mb={mb}>
        {shortAddress}
      </Text>
    );

  const accountMenu = address && (
    <LinkBox>
      <Flex align="center">
        <LinkOverlay as={NavLink} to="/portfolio">
          <QRPunkBlockie withQr={false} address={address.toLowerCase()} w={9} borderRadius={6} />
        </LinkOverlay>
        <Box ml={4}>
          {/* ToDo. Move to Utils */}
          <UserDisplayName textAlign="left" />
        </Box>
        <Tooltip label="Disconnect wallet">
          <Button ml={4} onClick={logoutOfWeb3Modal} variant="outline" size="sm">
            X
          </Button>
        </Tooltip>
      </Flex>
    </LinkBox>
  );

  const handleSignUpSuccess = () => {
    closePopover();
    toast({
      title: "You are now registered!",
      description: (
        <>
          Visit{" "}
          <Link href="/portfolio" textDecoration="underline">
            your portfolio
          </Link>{" "}
          to start building
        </>
      ),
      status: "success",
    });
  };

  const anonymousMenu = address && (
    <Popover placement="bottom-end" initialFocusRef={registerButtonRef} isOpen={isPopoverOpen} onClose={closePopover}>
      <PopoverTrigger>
        <Button variant="ghost" _hover={{ backgroundColor: "gray.50" }} w={9} p={0} onClick={openPopover}>
          <Box>
            <Icon as={HeroIconUser} w={6} h={6} color={secondaryFontColor} />
            <AvatarBadge boxSize={2} bg="red.500" borderRadius="full" top="4px" right="4px" />
          </Box>
        </Button>
      </PopoverTrigger>
      <Tooltip label="Disconnect wallet">
        <Button ml={4} onClick={logoutOfWeb3Modal} variant="outline" size="sm">
          X
        </Button>
      </Tooltip>
      <PopoverContent w={72}>
        <PopoverBody
          as={Flex}
          direction="column"
          px={9}
          py={10}
          _focus={{ background: "none" }}
          _active={{ background: "none" }}
        >
          <Text color={primaryFontColor} fontWeight="bold" textAlign="center" mb={1}>
            Register as a builder
          </Text>
          <Text color={secondaryFontColor} fontSize="sm" fontWeight="normal" textAlign="center" mb={6}>
            Sign a message with your wallet to create a builder profile.
          </Text>
          <Box m="auto" p="px" borderWidth="1px" borderColor={dividerColor} borderRadius={8}>
            <QRPunkBlockie address={address} w={19} borderRadius={6} />
          </Box>
          <UserDisplayName textAlign="center" mb={6} />
          <SignatureSignUp
            ref={registerButtonRef}
            userProvider={userProvider}
            address={address}
            onSuccess={handleSignUpSuccess}
            setUserRole={setUserRole}
          />
        </PopoverBody>
      </PopoverContent>
    </Popover>
  );

  const userMenu = isAnonymous ? anonymousMenu : accountMenu;

  return (
    <Flex align="center">
      {isAdmin && (
        <Badge colorScheme="red" mr={4}>
          admin
        </Badge>
      )}
      {isBuilder && (
        <Badge colorScheme="green" mr={4}>
          builder
        </Badge>
      )}
      {isWalletConnected ? userMenu : connectWallet}
    </Flex>
  );
}
Example #16
Source File: index.js    From javascript-mini-projects with The Unlicense 4 votes vote down vote up
export default function Home({ category, quote, start }) {
	const cat = useRef();
	const [author, setAuthor] = useState(quote.author);
	const [quotes, setQuotes] = useState(quote.content);
	const [val, setVal] = useState(false);
	const [bgImage, setBgImage] = useState("white");
	const [fontCol, setFontCol] = useState("black");
	const { reset } = useIdleTimer({
		timeout: 1000 * 60 * 3,
		onIdle: handleOnIdle,
	});

	function handleOnIdle() {
		cat.current.value =
			category[Math.floor(Math.random() * category.length)];
		genQuote();
		reset();
	}

	async function genQuote() {
		const response = await axios.get(
			`https://api.quotable.io/random?tags=${cat.current.value}`
		);
		setAuthor(response.data.author);
		setQuotes(response.data.content);
		let x = Math.floor(Math.random() * 256);
		let y = Math.floor(Math.random() * 256);
		let z = Math.floor(Math.random() * 256);
		let bgColor = "rgb(" + x + "," + y + "," + z + ")";
		setBgImage(bgColor);

		let luminance = (0.299 * x + 0.587 * y + 0.114 * z) / 255;
		let d = 0;
		if (luminance > 0.5) d = 0;
		// bright colors - black font
		else d = 255; // dark colors - white font

		setFontCol(`rgb(${d},${d},${d})`);

		setVal(!val);
	}

	return (
		<>
			<Head>
				<title>Random Quote Generator</title>
				<meta
					name="description"
					content="Generated by create next app"
				/>
				<link rel="preconnect" href="https://fonts.googleapis.com" />
				<link
					rel="preconnect"
					href="https://fonts.gstatic.com"
					crossOrigin="true"
				/>
				<link
					href="https://fonts.googleapis.com/css2?family=Prompt:wght@300&display=swap"
					rel="stylesheet"
				/>
			</Head>
			<Box minH="100vh" w="100vw" zIndex="-1" position="fixed"></Box>
			<Flex
				flexDir="column"
				alignItems="center"
				justifyContent="center"
				w="100vw"
				bg={bgImage}
				minH="100vh"
			>
				<Heading my="3rem" fontSize="2rem" color={fontCol}>
					Random Quote Generator
				</Heading>
				<Flex
					justifyContent="center"
					bg="purple"
					w="100vw"
					mb="3rem"
					p="1rem"
				>
					<Flex
						alignItems="center"
						justifyContent="space-around"
						w="30%"
						minW="200px"
					>
						<Text as="strong" color="white">
							Select a category :
						</Text>
						<Select
							maxW="250px"
							textTransform="capitalize"
							ref={cat}
							defaultValue={start}
							variant="outline"
							color="black"
							bgColor="white"
						>
							{category &&
								category.map((item) => (
									<option value={item} key={item}>
										{item}
									</option>
								))}
							{!category && <Spinner size="lg" />}
						</Select>
					</Flex>
				</Flex>
				<Box
					w="50%"
					minW="250px"
					bg="gray.100"
					boxShadow="inset 2px 2px 8px gray"
					borderRadius="lg"
					p="3rem"
					fontSize="1.8rem"
					fontFamily="Prompt"
				>
					<Text as="blockquote" fontWeight="semibold">
						{quotes}
					</Text>
					<Text as="i" d="block" textAlign="right" mt="2rem">
						~ {author}
					</Text>
				</Box>
				<Button onClick={genQuote} colorScheme="facebook" mt="3rem">
					Get New Quote
				</Button>
			</Flex>
		</>
	);
}