@chakra-ui/react#Grid JavaScript Examples
The following examples show how to use
@chakra-ui/react#Grid.
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: Footer.jsx From realtime-chat-supabase-react with Apache License 2.0 | 6 votes |
export default function Footer() {
return (
<Box position="fixed" bottom="0" width="100%">
<MessageForm />
<Grid
gridTemplateColumns="auto 1fr"
textAlign="center"
alignItems="center"
py="4px"
px="30px"
height="40px"
bg="white"
>
<GridItem justifySelf="start">
{/* Built by{" "} */}
{/* <a href="http://shimon-wosner.vercel.app" target="_blank"> */}
<a
href="https://twitter.com/shwosner"
target="_blank"
rel="noreferrer"
>
<FaTwitter style={{ display: "inline" }} />
@shwosner
</a>
</GridItem>
<GridItem justifySelf="end">
<a
href="https://github.com/shwosner/realtime-chat-supabase-react"
target="_blank"
rel="noreferrer"
>
<FaGithub style={{ display: "inline" }} /> Source code
</a>
</GridItem>
</Grid>
</Box>
);
}
Example #2
Source File: Message.jsx From realtime-chat-supabase-react with Apache License 2.0 | 5 votes |
export default function Message({ message, isYou }) {
const countyCode =
message.country && message.country !== "undefined"
? message.country.toLowerCase()
: "";
return (
<Box display="grid" justifyItems={isYou ? "end" : "start"}>
<Grid
templateRows="30px 1fr 25px"
templateColumns="1fr"
w="70%"
px="3"
py="2"
borderRadius="5px"
borderTopLeftRadius={isYou ? "5px" : "0"}
borderTopRightRadius={isYou ? "0" : "5px"}
bg={isYou ? "#dbfff9" : "#edf3f9"}
mt="5"
position="relative"
_after={{
position: "absolute",
content: "''",
width: 0,
height: 0,
borderStyle: "solid",
borderWidth: isYou ? "0px 0px 10px 10px" : "0px 10px 10px 0",
borderColor: isYou
? "transparent transparent transparent #dbfff9"
: "transparent #edf3f9 transparent transparent",
top: 0,
left: isYou ? "auto" : "-10px",
right: isYou ? "-10px" : "auto",
}}
>
<GridItem
fontWeight="500"
fontSize="md"
justifySelf="start"
color="gray.500"
mb="2"
>
<span>{message.username} </span>
{message.is_authenticated && (
<MdVerified
color="#1d9bf0"
style={{ display: "inline", marginRight: "5px" }}
/>
)}
{countyCode && (
<Box display="inline-block" fontSize="10px">
from {message.country}{" "}
<img
style={{ display: "inline-block", marginTop: "-4px" }}
src={`/flags/${countyCode}.png`}
alt={message.country}
/>
</Box>
)}
</GridItem>
<GridItem
justifySelf="start"
textAlign="left"
wordBreak="break-word"
fontSize="md"
fontFamily="Montserrat, sans-serif"
>
{message.text}
</GridItem>
<GridItem
color="gray"
fontSize="10px"
justifySelf="end"
alignSelf="end"
>
{dayjs(message.timestamp).fromNow()}
</GridItem>
</Grid>
</Box>
);
}
Example #3
Source File: Header.jsx From realtime-chat-supabase-react with Apache License 2.0 | 5 votes |
export default function Header() {
const { username, setUsername, auth, randomUsername } = useAppContext();
return (
<Grid
templateColumns="max-content 1fr min-content"
justifyItems="center"
alignItems="center"
bg="white"
position="sticky"
top="0"
zIndex="10"
borderBottom="20px solid #edf2f7"
>
<GridItem justifySelf="start" m="2">
<Image src="/logo.png" height="30px" ml="2" />
</GridItem>
{auth.user() ? (
<>
<GridItem justifySelf="end" alignSelf="center" mr="4">
Welcome <strong>{username}</strong>
</GridItem>
<Button
marginRight="4"
size="sm"
variant="link"
onClick={() => {
const { error } = auth.signOut();
if (error) return console.error("error signOut", error);
const username = randomUsername();
setUsername(username);
localStorage.setItem("username", username);
}}
>
Log out
</Button>
</>
) : (
<>
<GridItem justifySelf="end" alignSelf="end">
<NameForm username={username} setUsername={setUsername} />
</GridItem>
<Button
size="sm"
marginRight="2"
colorScheme="teal"
rightIcon={<FaGithub />}
variant="outline"
onClick={() =>
auth.signIn({
provider: "github",
})
}
>
Login
</Button>
</>
)}
</Grid>
);
}
Example #4
Source File: MeetupLayout.js From codeursenseine.com with MIT License | 4 votes |
MeetupLayout = ({ children, title }) => {
const data = useStaticQuery(graphql`
{
sponsors: allFile(
filter: {
sourceInstanceName: { eq: "sponsors" }
childMdx: { frontmatter: { isMeetupSponsor: { eq: true } } }
}
sort: { order: ASC, fields: childMdx___frontmatter___name }
) {
nodes {
childMdx {
frontmatter {
name
link
logo {
publicURL
}
}
}
}
}
associations: allFile(
filter: {
sourceInstanceName: { eq: "associations" }
internal: {}
extension: { eq: "mdx" }
}
sort: { fields: childMdx___frontmatter___name }
) {
nodes {
childMdx {
frontmatter {
name
link
logo {
publicURL
}
}
}
}
}
}
`);
return (
<Layout theme="meetups">
<Seo title={title} />
<Grid templateColumns={{ base: "1fr", md: "2.5fr 1fr" }} gap={8}>
<Box>{children}</Box>
<Stack spacing={10}>
<Stack spacing={6}>
<Heading as="h2" size="lg" fontWeight="normal" mb={8}>
Sponsors meetups
</Heading>
<Grid templateColumns="1fr 1fr" gap={4}>
{data.sponsors.nodes.map(({ childMdx: sponsor }) => (
<Card
isLink
as="a"
href={sponsor.frontmatter.link}
title={sponsor.frontmatter.name}
key={sponsor.frontmatter.name}
p={0}
>
<Image
src={sponsor.frontmatter.logo.publicURL}
alt={sponsor.frontmatter.name}
/>
</Card>
))}
</Grid>
</Stack>
<Stack spacing={6}>
<Heading as="h2" size="lg" fontWeight="normal" mb={8}>
Associations
</Heading>
<Grid templateColumns="1fr 1fr" gap={4}>
{data.associations.nodes.map(({ childMdx: association }) => (
<Card
isLink
as="a"
href={association.frontmatter.link}
title={association.frontmatter.name}
key={association.frontmatter.name}
p={0}
>
<Flex align="center" justify="center">
<Image
src={association.frontmatter.logo.publicURL}
alt={association.frontmatter.name}
/>
</Flex>
</Card>
))}
</Grid>
</Stack>
</Stack>
</Grid>
</Layout>
);
}
Example #5
Source File: ConferenceCard.js From codeursenseine.com with MIT License | 4 votes |
ConferenceCard = ({ conference, speakers }) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const capitalizeFirstLetter = (string) =>
string.charAt(0).toUpperCase() + string.slice(1);
if (conference?.childMdx?.frontmatter?.type === "break") {
return (
<Card variant="primary" mt={2}>
<Stack align="center">
<Text>{conference?.childMdx?.frontmatter?.title}</Text>
</Stack>
</Card>
);
}
return (
<Stack>
<Grid
templateColumns={["repeat(1, 1fr)", "repeat(1, 1fr) repeat(1, 4fr)"]}
mt={3}
>
<Stack mr={3}>
<Flex
display={["none", "flex"]}
flexDirection="column"
justifyContent="space-between"
h="100%"
borderColor="blue.50"
borderStyle="solid"
borderTopWidth={1}
borderBottomWidth={1}
>
<Text color="blue.600">
{conference.childMdx.frontmatter.startHour}
</Text>
<Text color="blue.600">
{conference.childMdx.frontmatter.endHour}
</Text>
</Flex>
<Stack display={["block", "none"]} mb={2}>
<Text color="blue.600">
{`${conference.childMdx.frontmatter.startHour} - ${conference.childMdx.frontmatter.endHour}`}
</Text>
</Stack>
{conference.childMdx.frontmatter.isKeynote && (
<Badge colorScheme="brand" width="fit-content">
Keynote
</Badge>
)}
</Stack>
<Card
borderLeftWidth={2}
borderLeftColor="brand.600"
onClick={onOpen}
w="full"
isLink
>
<Heading fontSize="md">
{conference.childMdx.frontmatter.title}
</Heading>
{speakers?.map((speaker) => (
<SpeakerPreview
key={speaker.childMdx.frontmatter.slug}
speaker={speaker}
/>
))}
<Center>
<Button
colorScheme="brand"
variant="link"
width="fit-content"
mt={2}
>
Voir les détails et s'inscrire
</Button>
</Center>
</Card>
</Grid>
<Drawer size="md" isOpen={isOpen} placement="right" onClose={onClose}>
<DrawerOverlay>
<DrawerContent>
<DrawerCloseButton />
<DrawerHeader>
<Stack alignItems="center" display="flex" flexDirection="row">
<Text fontSize="sm" mt={2}>
{capitalizeFirstLetter(
dayjs(conference.childMdx.frontmatter.eventDate).format(
"dddd D MMM"
)
)}{" "}
{`${conference.childMdx.frontmatter.startHour} - ${conference.childMdx.frontmatter.endHour}`}
</Text>
{conference.childMdx.frontmatter.isKeynote && (
<Badge
ml={3}
h="fit-content"
colorScheme="brand"
width="fit-content"
>
Keynote
</Badge>
)}
</Stack>
<Text>{conference.childMdx.frontmatter.title}</Text>
<Stack mt={3}>
{speakers?.map((speaker) => (
<SpeakerPreview
key={speaker.childMdx.frontmatter.slug}
speaker={speaker}
/>
))}
</Stack>
</DrawerHeader>
<DrawerBody overflow="auto">
<MDXRenderer>{conference.childMdx.body}</MDXRenderer>
</DrawerBody>
{conference.childMdx.frontmatter.meetupLink && (
<DrawerFooter display="flex" flexDirection="column">
<Button isFullWidth variant="outline" mb={3} onClick={onClose}>
Fermer
</Button>
<Button
colorScheme="brand"
as={Link}
target="_blank"
to={conference.childMdx.frontmatter.meetupLink}
isFullWidth
>
S'inscrire
</Button>
</DrawerFooter>
)}
</DrawerContent>
</DrawerOverlay>
</Drawer>
</Stack>
);
}
Example #6
Source File: index.js From codeursenseine.com with MIT License | 4 votes |
Meetups = ({ data }) => {
const meetups = data.meetups.nodes.filter(
(meetup) =>
meetup.childMdx &&
meetup.childMdx.frontmatter &&
meetup.childMdx.frontmatter.meetup_date !== null
);
if (process.env.GATSBY_ARCHIVE) {
return <RedirectCodeursEnSeine path="/meetups" />;
}
return (
<Layout theme="meetups">
<Seo
title="Meetups"
meta={[
{
property: `og:image`,
content: `${process.env.GATSBY_ORIGIN}/images/meetups/social.jpg`,
},
]}
/>
<Grid templateColumns={{ base: "1fr", md: "2.5fr 1fr" }} gap={8}>
<Box>
<Stack spacing={6}>
<Heading as="h1" mb={6}>
Tous les meetups
</Heading>
{meetups.map(({ childMdx: meetup, name }) => (
<Card key={name} as={Link} to={generateMeetupLink(meetup)} isLink>
<Stack>
<Box>
<Heading
as="h3"
color="brand.700"
size="lg"
fontWeight="normal"
>
{parse(meetup.frontmatter.title)}
</Heading>
{meetup.frontmatter.excerpt !== "" && (
<Text>{meetup.frontmatter.excerpt}</Text>
)}
</Box>
<Box>
<Text fontWeight="bold">
Meetup le {meetup.frontmatter.meetup_date} de{" "}
{meetup.frontmatter.meetup_start_time} Ã {" "}
{meetup.frontmatter.meetup_end_time}
</Text>
<Text color="gray.500">
{meetup.frontmatter.meetup_location}
</Text>
</Box>
</Stack>
</Card>
))}
</Stack>
</Box>
<Stack spacing={10}>
<Stack spacing={6}>
<Heading as="h2" size="lg" fontWeight="normal" mb={8}>
Sponsors meetups
</Heading>
<Grid templateColumns="1fr 1fr" gap={4}>
{data.sponsors.nodes.map(({ childMdx: sponsor }) => (
<Card
isLink
as="a"
href={sponsor.frontmatter.link}
title={sponsor.frontmatter.name}
key={sponsor.frontmatter.name}
p={0}
>
<Image
src={sponsor.frontmatter.logo.publicURL}
alt={sponsor.frontmatter.name}
/>
</Card>
))}
</Grid>
<a
href="https://www.devoxx.fr/"
target="_blank"
rel="noopener noreferrer"
>
<Image
src="/images/meetups/devoxx-france-logo-2022-carre.png"
alt="Devoxx France 2022"
/>
</a>
</Stack>
<Stack spacing={6}>
<Heading as="h2" size="lg" fontWeight="normal" mb={8}>
Associations
</Heading>
<Grid templateColumns="1fr 1fr" gap={4}>
{data.associations.nodes.map(({ childMdx: association }) => (
<Card
isLink
as="a"
href={association.frontmatter.link}
title={association.frontmatter.name}
key={association.frontmatter.name}
p={0}
>
<Flex align="center" justify="center">
<Image
src={association.frontmatter.logo.publicURL}
alt={association.frontmatter.name}
/>
</Flex>
</Card>
))}
</Grid>
</Stack>
</Stack>
</Grid>
</Layout>
);
}
Example #7
Source File: index.js From codeursenseine.com with MIT License | 4 votes |
Organisers = ({ pageContext }) => {
const { organisers } = pageContext;
const socials = [
{ name: "twitter", icon: <FaTwitter /> },
{ name: "linkedin", icon: <FaLinkedin /> },
{ name: "github", icon: <FaGithub /> },
];
return (
<Layout theme="ces">
<OGImage path="/images/ces/social.jpg" />
<Seo title="Organisateurs" />
<Heading as="h1" mb={8}>
Organisateurs
</Heading>
<Stack spacing={6}>
<Heading size="lg">Associations</Heading>
<Text>
Codeurs en Seine est une association dont le but est la promotion et
le partage des pratiques et des nouveautés technologiques entre les
acteurs du développement informatique.
</Text>
<Text>
En plus de la conférence annuelle Codeurs en Seine, nous organisons
des meetups et des ateliers tout au long de l'année, sur Rouen et ses
environs.
</Text>
<Text>
Codeurs en Seine représente le Normandy Java User Group et Normandy
Agile User Group.
</Text>
<Text>
Elle est également une étape de l'
<A href="http://www.agiletour.org/">Agile Tour</A>.
</Text>
<Heading size="lg">Équipe</Heading>
<Text mb={8}>
Codeurs en Seine est propulsé par une équipe de bénévoles passionnés :
</Text>
<Grid templateColumns="repeat(auto-fit, minmax(6rem, 1fr))" gap={6}>
{organisers.map((organiser) => (
<Stack
alignItems="center"
key={organiser.childMdx.frontmatter.name}
>
<AspectRatio ratio={1} w="6em" maxW="100%">
<Image
fallbackSrc="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
src={organiser.childMdx.frontmatter.image.publicURL}
alt={organiser.childMdx.frontmatter.name}
boxShadow="brand"
objectFit="cover"
borderRadius={4}
/>
</AspectRatio>
<Text textAlign="center" fontSize="sm">
{organiser.childMdx.frontmatter.name}
</Text>
<Flex flexWrap="wrap">
{socials.map(
(social) =>
organiser.childMdx.frontmatter[social.name] && (
<IconButton
key={social.name}
as="a"
target="_blank"
href={organiser.childMdx.frontmatter[social.name]}
aria-label={`${organiser.childMdx.frontmatter.name} ${social.name}`}
icon={social.icon}
variant="ghost"
colorScheme="brand"
size="sm"
d="inline-flex"
/>
)
)}
</Flex>
</Stack>
))}
</Grid>
</Stack>
</Layout>
);
}
Example #8
Source File: index.js From codeursenseine.com with MIT License | 4 votes |
SponsorsPage = ({ pageContext }) => {
const { sponsors } = pageContext;
const data = useStaticQuery(graphql`
{
placeholderImage: file(
relativePath: { eq: "ces/dossier-sponsoring.jpg" }
) {
childImageSharp {
gatsbyImageData(width: 250, quality: 80, layout: CONSTRAINED)
}
}
}
`);
const sponsorLevels = ["platinium", "gold", "silver", "bronze"];
return (
<Layout theme="ces">
<OGImage path="/images/ces/social.jpg" />
<Seo title="Sponsors" />
<Heading as="h1" mb={8}>
Devenir Sponsor
</Heading>
<Grid templateColumns={["1fr", "1fr", "1fr 2fr"]} gap={8} mb={8}>
<Box maxWidth="250px">
<A
d="block"
boxShadow="brand"
overflow="hidden"
borderRadius="md"
href="https://drive.google.com/file/d/1zclVxBxeUZFUxX2kxVXCoAW8CnFr3p40/view?usp=sharing"
title="Dossier de sponsoring"
target="_blank"
>
<GatsbyImage
image={data.placeholderImage.childImageSharp.gatsbyImageData}
alt="Première page du dossier de sponsoring"
/>
</A>
</Box>
<Box>
<Stack spacing={8}>
<Text>
Codeurs en Seine est à la recherche de sponsors pour proposer un
événement d'une qualité toujours meilleure.
</Text>
<Text>
Les partenaires des éditions précédentes ont confirmé la
visibilité offerte par ce sponsoring, surtout dans le cadre d'une
politique de recrutement.
</Text>
<Text>
Si vous souhaitez soutenir l'événement, téléchargez{" "}
<A
href="https://drive.google.com/file/d/1zclVxBxeUZFUxX2kxVXCoAW8CnFr3p40/view?usp=sharing"
target="_blank"
>
le dossier de sponsoring
</A>
,{" "}
<A
href="https://docs.google.com/document/d/14dtwH8QfzXuvPddlbo2fYgRy78RPtwwU1vPsH9tdgr4/edit?usp=sharing"
target="_blank"
>
la convention de sponsoring
</A>{" "}
et contactez-nous à l'adresse{" "}
<A href="mailto:[email protected]">
[email protected]
</A>
.
</Text>
<ButtonGroup>
<Button
as="a"
href="https://drive.google.com/file/d/1zclVxBxeUZFUxX2kxVXCoAW8CnFr3p40/view?usp=sharing"
target="_blank"
colorScheme="brand"
>
Dossier de sponsoring
</Button>
<Box display="flex" flexDir="column">
<Button
as="a"
href="https://docs.google.com/document/d/14dtwH8QfzXuvPddlbo2fYgRy78RPtwwU1vPsH9tdgr4/edit?usp=sharing"
target="_blank"
colorScheme="brand"
variant="outline"
>
Convention de sponsoring
</Button>
<Button
as="a"
href="https://docs.google.com/document/d/1oI6vAZBttTuSgxHH__LCVS1XV8j7wdiozc1TEzuVEhk/edit?usp=sharing"
target="_blank"
colorScheme="brand"
variant="outline"
marginTop={4}
>
?? Sponsorship agreement
</Button>
</Box>
</ButtonGroup>
</Stack>
</Box>
</Grid>
<Divider mb={6} />
<Stack spacing={6}>
{sponsorLevels.map((level) => {
const thisLevelSponsors = sponsors.filter(
(sponsor) => sponsor.frontmatter.sponsor === level
);
return (
thisLevelSponsors.length > 0 && (
<Stack spacing={6} key={level}>
<Heading size="lg" color="brand.700" fontWeight="normal">
Sponsors {level}
</Heading>
<SimpleGrid columns={{ base: 1, sm: 2, lg: 3 }} gap={8}>
{thisLevelSponsors.map((sponsor, index) => (
<SponsorCard
key={index}
name={sponsor.frontmatter.name}
link={sponsor.frontmatter.link}
logoSrc={sponsor.frontmatter?.logo?.publicURL}
excerpt={sponsor.excerpt}
isDonator={sponsor.frontmatter.isDonator}
>
{sponsor.body}
</SponsorCard>
))}
</SimpleGrid>
<Divider />
</Stack>
)
);
})}
</Stack>
</Layout>
);
}
Example #9
Source File: ActivityPage.js From DAOInsure with MIT License | 4 votes |
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 #10
Source File: ClaimsPage.js From DAOInsure with MIT License | 4 votes |
function ClaimsPage() {
const { textileClient } = useContext(AppContext);
const [openClaims, setOpenClaims] = useState();
const [isLoadingOpenClaims, setIsLoadingOpenClaims] = useState(true);
const web3Context = useContext(Web3Context);
const {
fetchAllProposals,
allProposalsArray,
openProposalsArray,
acceptedProposalsArray,
rejectedProposalsArray,
daoMemberCount,
setDaoMemberCount,
} = web3Context;
useEffect(() => {
async function init() {
console.log(textileClient);
if (textileClient) {
// textile database querying the thread using threadId and collection where claims are present.
let openClaims = await queryThread(
textileClient,
"bafkyspsyykcninhqn4ht6d6jeqmzq4cepy344akmkhjk75dmw36wq4q",
"claimsData",
{}
);
console.log(openClaims);
setOpenClaims(openClaims);
setIsLoadingOpenClaims(false);
}
}
init();
}, [textileClient]);
useEffect(() => {
fetchAllProposals();
console.log(openProposalsArray);
}, []);
return (
<Grid
height='calc(100vh - 64px)'
px='250px'
py='20px'
width='100%'
templateColumns='3fr 1fr'
gridGap={5}
alignItems='flex-start'>
<Tabs variant='soft-rounded' colorScheme='whatsapp'>
<TabList justifyContent='space-between'>
<HStack>
<Tab>
Open Claims{" "}
<GreenTag>{openProposalsArray.length}</GreenTag>
</Tab>
<Tab variant='solid'>
Accepted Claims{" "}
<GreenTag>{acceptedProposalsArray.length}</GreenTag>
</Tab>
<Tab variant='solid'>
Rejected Claims{" "}
<GreenTag>{rejectedProposalsArray.length}</GreenTag>
</Tab>
</HStack>
<Link to='/makeClaim'>
<Button colorScheme='whatsapp'>+ Make a Claim</Button>
</Link>
</TabList>
<TabPanels>
<TabPanel py={4} px={0}>
<ClaimsList claims={openProposalsArray} />
</TabPanel>
<TabPanel py={4} px={0}>
<ClaimsList claims={acceptedProposalsArray} />
</TabPanel>
<TabPanel py={4} px={0}>
<ClaimsList claims={rejectedProposalsArray} />
</TabPanel>
</TabPanels>
</Tabs>
<Stats
claims={
acceptedProposalsArray.length +
rejectedProposalsArray.length
}
daoMemberCount={daoMemberCount}
/>
</Grid>
);
}
Example #11
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 #12
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 #13
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 #14
Source File: Player.jsx From bottle-radio with MIT License | 4 votes |
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 #15
Source File: PlayerEmbed.jsx From bottle-radio with MIT License | 4 votes |
PlayerEmbed = () => {
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 [nowPlaying, setNowPlaying] = useState(["No data", "No data"]);
const { colorMode } = useColorMode();
const colorHover = { light: "white", dark: "black" };
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]);
}
};
updateStats();
setInterval(() => {
updateStats();
}, 10000);
}, [variables.REACT_ICECAST_URL]);
const togglePlay = () => {
let player = document.getElementById("player");
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;
};
return (
<div>
<Flex
direction="column"
justify="center"
align="center"
width="100%"
height="100%"
bg="transparent"
>
<Box>
<Grid
m={2}
p={2}
templateColumns="auto 1fr"
alignItems="center"
gap={1}
>
<Box
gridRow="1/4"
size="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="right">
<strong>{nowPlaying[0]}</strong>
</Text>
<Text m={0} align="right">
{nowPlaying[1]}
</Text>
<Flex direction="row" justify="center" maxWidth={400} p={2}>
<Slider
defaultValue={100}
min={0}
max={100}
step={10}
onChange={changeVolume}
width={80}
>
<SliderTrack style={{ height: "5px" }}>
<SliderFilledTrack bg="tomato" />
</SliderTrack>
<SliderThumb size={2} />
</Slider>
<Box
w="20px"
h="20px"
as={muted ? FaVolumeMute : FaVolumeUp}
ml={3}
/>
<audio
id="player"
autoPlay
onPlay={() => setPlaying(true)}
onPause={() => setPlaying(false)}
onLoadStart={() => setLoading(true)}
onLoadedData={() => setLoading(false)}
>
<source
src={variables.REACT_ICECAST_URL + "radio.mp3"}
type="audio/mp3"
/>
Your browser does not support the audio element.
</audio>
</Flex>
</Grid>
</Box>
</Flex>
</div>
);
}