@chakra-ui/react#Container JavaScript Examples
The following examples show how to use
@chakra-ui/react#Container.
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: podcasts.js From grandcast.fm with Apache License 2.0 | 6 votes |
Podcasts = () => {
const [getPodcasts, { data }] = useLazyQuery(PodcastSearchQuery)
const { isSignedIn } = useAuth()
const [searchString, setSearchString] = useState('')
return (
<Container>
{!isSignedIn() && <SignIn />}
{isSignedIn() && (
<div>
<FormControl id="podcastsearch">
<FormLabel>Search podcasts</FormLabel>
<Flex>
<Input onChange={(e) => setSearchString(e.target.value)} />
<Button
ml={4}
onClick={() =>
getPodcasts({ variables: { searchTerm: searchString } })
}
>
Search
</Button>
</Flex>
</FormControl>
<VStack>
{data?.podcastSearch.map((p) => {
return <Podcast podcast={p} />
})}
</VStack>
</div>
)}
</Container>
)
}
Example #2
Source File: BlobActionBar.js From blobs.app with MIT License | 6 votes |
BlobActionBar = () => (
<Box mt="10">
<Container centerContent maxW="sm">
<HStack spacing="24px">
<HtmlCodeModalButton />
<RandomizerBtn />
<FlutterCodeModalButton />
</HStack>
</Container>
</Box>
)
Example #3
Source File: Slider.js From blobs.app with MIT License | 6 votes |
Slider = ({ name, value, min, max, onChange, info }) => (
<Box my="8">
<Container centerContent maxW="sm">
<Flex justify="space-between" w="100%" mb="2">
<Text fontSize="sm" variant="subtle">
{name}
</Text>
<Hint text={info} />
</Flex>
<ChakSlider
value={value}
min={min}
max={max}
onChange={onChange}
focusThumbOnChange={false}
>
<SliderTrack bg="gray.200" _dark={{ bg: 'gray.900', opacity: 0.5 }}>
<Box position="relative" right={10} />
<SliderFilledTrack bg="gray.400" _dark={{ bg: 'gray.400' }} />
</SliderTrack>
<Tooltip label={value} aria-label={value} hasArrow variant="default">
<SliderThumb
boxSize={5}
borderWidth="3px"
borderColor="gray.400"
_focus={{ bg: 'gray.400' }}
_dark={{ bg: 'blue.800' }}
/>
</Tooltip>
</ChakSlider>
</Container>
</Box>
)
Example #4
Source File: Layout.js From blobs.app with MIT License | 6 votes |
Layout = ({ children }) => {
const theme = useColorModeValue('light', 'dark');
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`);
return (
<Provider store={store}>
<Box className={theme}>
<Container
maxW="container.xl"
flex="1"
display="flex"
flexDir="column"
minH="100vh"
>
<Box as="main" flex="1" display="flex" flexDir="column">
{children}
</Box>
<Footer siteTitle={data.site.siteMetadata?.title || 'Title'} />
</Container>
</Box>
</Provider>
);
}
Example #5
Source File: ActivityView.jsx From scaffold-directory with MIT License | 5 votes |
export default function ActivityView() {
const [eventsFeed, setEventFeeds] = useState([]);
const [isLoadingEvents, setIsLoadingEvents] = useState(false);
const { secondaryFontColor } = useCustomColorModes();
useEffect(() => {
const updateEvents = async () => {
setIsLoadingEvents(true);
const events = await getAllEvents(25);
setEventFeeds(events);
setIsLoadingEvents(false);
};
updateEvents();
}, []);
return (
<Container maxW="container.md" centerContent>
<Heading as="h1" mb="4">
Activity feed
</Heading>
<Text color={secondaryFontColor} textAlign="center" mb={10}>
Last 25 things happening at SRE.
</Text>
{isLoadingEvents ? (
<Box w="100%" maxW="500px">
<SkeletonText mt="4" noOfLines={10} spacing="4" />
</Box>
) : (
<Table>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Time</Th>
<Th>Action</Th>
</Tr>
</Thead>
<Tbody>
{eventsFeed.map(event => (
<EventRow key={`${event.timestamp}_${event.payload.userAddress}`} event={event} />
))}
</Tbody>
</Table>
)}
</Container>
);
}
Example #6
Source File: Chat.jsx From realtime-chat-supabase-react with Apache License 2.0 | 5 votes |
export default function Chat() {
const [height, setHeight] = useState(window.innerHeight - 205);
const {
scrollRef,
onScroll,
scrollToBottom,
isOnBottom,
unviewedMessageCount,
} = useAppContext();
useEffect(() => {
window.addEventListener("resize", () => {
setHeight(window.innerHeight - 205);
});
}, []);
return (
<Container maxW="600px" pb="20px">
<Box
bg="white"
p="5"
overflow="auto"
borderRadius="10px"
height={height}
onScroll={onScroll}
ref={scrollRef}
>
<Messages />
{!isOnBottom && (
<div
style={{
position: "sticky",
bottom: 8,
// right: 0,
float: "right",
cursor: "pointer",
}}
onClick={scrollToBottom}
>
{unviewedMessageCount > 0 ? (
<Badge
ml="1"
fontSize="0.8em"
colorScheme="green"
display="flex"
borderRadius="7px"
padding="3px 5px"
alignItems="center"
>
{unviewedMessageCount}
<BsChevronDoubleDown style={{ marginLeft: "3px" }} />
</Badge>
) : (
<BsChevronDoubleDown style={{ marginLeft: "3px" }} />
)}
</div>
)}
</Box>
</Container>
);
}
Example #7
Source File: MessageForm.jsx From realtime-chat-supabase-react with Apache License 2.0 | 5 votes |
export default function MessageForm() {
const { supabase, username, country, auth } = useAppContext();
const [message, setMessage] = useState("");
const toast = useToast();
const [isSending, setIsSending] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setIsSending(true);
if (!message) return;
setMessage("");
try {
const { error } = await supabase.from("messages").insert([
{
text: message,
username,
country,
is_authenticated: auth.user() ? true : false,
},
]);
if (error) {
console.error(error.message);
toast({
title: "Error sending",
description: error.message,
status: "error",
duration: 9000,
isClosable: true,
});
return;
}
console.log("Sucsessfully sent!");
} catch (error) {
console.log("error sending message:", error);
} finally {
setIsSending(false);
}
};
return (
<Box py="10px" pt="15px" bg="gray.100">
<Container maxW="600px">
<form onSubmit={handleSubmit} autoComplete="off">
<Stack direction="row">
<Input
name="message"
placeholder="Enter a message"
onChange={(e) => setMessage(e.target.value)}
value={message}
bg="white"
border="none"
autoFocus
/>
<IconButton
// variant="outline"
colorScheme="teal"
aria-label="Send"
fontSize="20px"
icon={<BiSend />}
type="submit"
disabled={!message}
isLoading={isSending}
/>
</Stack>
</form>
<Box fontSize="10px" mt="1">
Warning: do not share any sensitive information, it's a public chat
room ?
</Box>
</Container>
</Box>
);
}
Example #8
Source File: App.js From interspace.chat with GNU General Public License v3.0 | 4 votes |
EasterEgg = () => {
const [toggle, setToggle] = useState(false);
const [openClaim, setOpenClaim] = useState(false);
const ref = useRef(null);
const claimRef = useRef(null);
const responsiveButtonSize = useBreakpointValue({base: 'sm', lg: 'md'})
const handleToggle = () => {
if (typeof window !== "undefined") {
setToggle(!toggle);
ref.current.classList.remove("found");
}
};
// const claimNFT = () => {
// if (typeof window !== "undefined") {
// setOpenClaim(!openClaim);
// // setToggle(!toggle);
// // ref.current.classList.remove("found");
// }
// };
return (
<>
<Box
ref={ref}
className="ee1"
bg="rgba(0,0,0,0.3)"
boxShadow="0 0 15px rgba(0,0,0,0.6)"
backdropFilter="blur(7px)"
color="white"
position="fixed"
bottom={0}
left={0}
right={0}
maxW="100vw"
textAlign="center"
height={{base: '150px', md: "auto"}}
opacity={0}
// transform="translateY(100px)"
transition="transform 0.3s 0.2s ease-in-out, opacity 0.3s 0.3s ease-in-out"
zIndex={0}
overflowX="clip"
sx={{
h4: {
fontSize: "2vmax",
fontWeight: 700,
},
"&.found": {
opacity: 1,
transform: "translateY(0)",
zIndex: 2003,
},
}}
>
{openClaim && (
<Button
position="absolute"
bottom={20}
right={6}
colorScheme="pink"
bg="#FF61E6"
boxShadow="0 0 10px rgba(0, 0, 0, 0.6)"
size="sm"
transition="all 0.3s 0.8s ease"
// transform={`translateY(${openClaim ? 0 : "-70px"})`}
onClick={() => setOpenClaim(!openClaim)}
zIndex={2004}
>
Close the claimer
</Button>
)}
<Box
d="flex"
position="relative"
alignItems="center"
justifyContent="space-around"
flexFlow="row nowrap"
mx="auto"
maxW={{base: '100%', md: "5xl"}}
py={3}
>
<Image src={BabyOctoGif} boxSize={{base: '35px', xl:"100px"}} objectFit="cover" />
<Box flex={1}>
<Text as="h4">
<span role="img" aria-label="Octo emoji">
?
</span>{" "}
Nova's blessings!!{" "}
<span role="img" aria-label="Octo emoji">
?
</span>
</Text>
<Text as="p" fontWeight={500}>
Welcome Anon!{" "}
<span role="img" aria-label="Cheers/Clinking glasses emoji">
?
</span>
<br />
You noticed little octo, all alone in space.{" "}
<span role="img" aria-label="Loved up emoji">
?
</span>{" "}
<br /> For that Nova will bestow wonderment upon you! Do you wish
to accept the gift?
<br />
</Text>
<Button
href="#"
colorScheme="pink"
bg="#FF61E6"
size={responsiveButtonSize}
mt={5}
onClick={() => setOpenClaim(!openClaim)}
>
Claim your NFT
</Button>
</Box>
<Image src={BabyOctoGif} boxSize={{base: '35px', xl:"100px"}} objectFit="cover" />
<IconButton
onClick={handleToggle}
colorScheme="ghost"
pos="absolute"
top={3}
right={0}
size="sm"
aria-label="Close easter egg"
icon={<CloseIcon />}
zIndex={2001}
/>
</Box>
</Box>
{openClaim && (
<Box
ref={claimRef}
position="fixed"
top="12.5vh"
left={0}
height="75vh"
minH="75vh"
width="100vw"
boxShadow="0 0 30px rgba(0,0,0,0.8)"
// opacity={onScreen ? 1 : 0}
transition="opacity 1.2s 0.8s ease-in-out"
zIndex={2003}
sx={{
bg: "rgba(25,0,50,0.4)",
backdropFilter: "blur(7px)",
}}
>
<Container maxW={{base: '100%', md: "2xl"}} height="100%" py={12} align="center">
<MinterInstance />
</Container>
<Box
display="flex"
position="absolute"
bottom={0}
right={0}
width="100%"
textAlign="center"
>
<Link
href="https://testnets.opensea.io/assets?search[query]=0x91BBa1e0EE2DCC8d78Fa017588614f328d6d1885"
isExternal
fontWeight={700}
fontSize="0.7vmax"
// d="inline-block"
mx="auto"
p={3}
bg="linear-gradient(90.24deg, #640DFB99 0.3%, rgba(100, 13, 251, 0.9) 80.16%)"
borderRadius="5px 5px 0 0"
boxShadow="0 0 5px rgba(0,0,0,0.6)"
overflow="clip"
>
<span role="img" aria-label="Attention!">
?
</span>{" "}
Need more NFTs? View the contract on OpenSea. <ExternalLinkIcon />
</Link>
</Box>
</Box>
)}
</>
);
}
Example #9
Source File: ApplySection.js From interspace.chat with GNU General Public License v3.0 | 4 votes |
ApplySection = () => {
const ref = useRef(null);
const onScreen = useOnScreen(ref);
const [openSpeakerApplication, setOpenSpeakerApplication] = useState(false);
const [openContributorApplication, setOpenContributorApplication] = useState(
false
);
const [openPerformerApplication, setOpenPerformerApplication] = useState(
false
);
const [openSponsorApplication, setOpenSponsorApplication] = useState(false);
return (
<Box as="section" id="apply" position="relative">
<Box
ref={ref}
className="__content"
width="100%"
transform={`translate3d(${onScreen ? 0 : "-70px"}, 0, 0)`}
opacity={onScreen ? 1 : 0}
transition="transform 0.3s 0.4s ease-in-out, opacity 0.6s 0.5s ease-in"
willChange={true}
>
<Box className="__content__body" d={{base: 'unset', md: "flex"}} w="100%" flexFlow={{base: 'column wrap', md: "row nowrap"}} alignItems="center" justifyContent="space-between">
<Container
maxW={{base: '100%', md: "2xl"}}
>
<Text
as="h2"
>
Apply here
</Text>
{/* <span className="fest-dates">9 - 23rd JUNE</span> */}
</Container>
<Container maxW={{base: '100%', md: "2xl"}} p={0} mt={{base: 5, md: 0}}>
<Box
maxW={{base: '100%', md: "2xl"}}
p={{ base: 8, md: 12 }}
sx={{
bg: "rgba(255,255,255,0.1)",
backdropFilter: "blur(7px)",
borderRadius: "5px 30px 10px 0",
boxShadow: "0 0 30px #00000070",
}}
>
<SimpleGrid columns={{ base: 1 }} spacing={0}>
<Stack spacing={{base: 2, md: 4}} >
<Text
textTransform={"uppercase"}
fontWeight={500}
fontSize={{ base: "2.2vmin", md: "0.7vmax" }}
className="gradient"
p={0}
alignSelf={"flex-start"}
rounded={"md"}
>
<span role="img" aria-label="Yay, come join us!">
?
</span>{" "}
Join the party!{" "}
<span role="img" aria-label="Yay, come join us!">
?
</span>
</Text>
<Text as="h3" mt={1}>
<span>MetaFest2 needs YOU</span>
<span
className="gradient"
role="img"
aria-label="Pointing at the forms below"
>
?
</span>
</Text>
<Text as="p" >
What is an event without amazing folks like you! People
who want to help organise & greet, tell us about their
projects, teach, sing, code...we'd love to see you. Apply
below.
</Text>
<Stack spacing={4} divider={<StackDivider />}>
<Feature
icon={SpeakerIcon}
iconBg={"yellow.900"}
text={"Speakers"}
call={() =>
setOpenSpeakerApplication(!openSpeakerApplication)
}
/>
<Feature
icon={ContributorIcon}
iconBg={"green.900"}
text={"Contributors"}
call={() =>
setOpenContributorApplication(!openContributorApplication)
}
/>
<Feature
icon={PerformerIcon}
iconBg={"purple.900"}
text={"Performers"}
call={() =>
setOpenPerformerApplication(!openPerformerApplication)
}
/>
<Feature
icon={SponsorIcon}
iconBg={"purple.900"}
text={"Sponsors"}
call={() =>
setOpenSponsorApplication(!openSponsorApplication)
}
/>
</Stack>
</Stack>
</SimpleGrid>
</Box>
</Container>
</Box>
</Box>
{openSpeakerApplication && (
<>
<Button
position="absolute"
bottom={{ base: 10, md: 20 }}
aria-label="Open the speaker application form"
right={6}
colorScheme="pink"
bg="#FF61E6"
boxShadow="0 0 10px rgba(0, 0, 0, 0.6)"
size="sm"
transition="all 0.3s 0.8s ease"
transform={`translateY(${openSpeakerApplication ? 0 : "-70px"})`}
onClick={() => setOpenSpeakerApplication(!openSpeakerApplication)}
zIndex={2003}
>
Close form
</Button>
<Box
ref={ref}
position="absolute"
top="12.5vh"
left={0}
height="75vh"
minH="75vh"
width="100vw"
sx={{
bg: "rgba(25,0,50,0.4)",
backdropFilter: "blur(7px)",
}}
boxShadow="0 0 30px rgba(0,0,0,0.8)"
opacity={onScreen ? 1 : 0}
transition="opacity 1.2s 0.8s ease-in-out"
zIndex={2001}
overflowY="scroll"
>
<AirtableSpeakerInstance />
</Box>
</>
)}
{openContributorApplication && (
<>
<Button
aria-label="Open the contributor application form"
position="absolute"
bottom={{base: 10, md: 20}}
right={6}
colorScheme="pink"
bg="#FF61E6"
boxShadow="0 0 10px rgba(0, 0, 0, 0.6)"
size="sm"
transition="all 0.3s 0.8s ease"
transform={`translateY(${
openContributorApplication ? 0 : "-70px"
})`}
onClick={() =>
setOpenContributorApplication(!openContributorApplication)
}
zIndex={2002}
>
Close form
</Button>
<Box
ref={ref}
position="absolute"
top="12.5vh"
left={0}
height="75vh"
minH="75vh"
midth="100vw"
sx={{
bg: "rgba(25,0,50,0.4)",
backdropFilter: "blur(7px)",
}}
boxShadow="0 0 30px rgba(0,0,0,0.8)"
opacity={onScreen ? 1 : 0}
transition="opacity 1.2s 0.8s ease-in-out"
zIndex={2001}
overflowY="scroll"
>
<AirtableContributorInstance />
</Box>
</>
)}
{openPerformerApplication && (
<>
<Button
aria-label="Open the performer application form"
position="absolute"
bottom={{base: 10, md: 20}}
right={6}
colorScheme="pink"
bg="#FF61E6"
boxShadow="0 0 10px rgba(0, 0, 0, 0.6)"
size="sm"
transition="all 0.3s 0.8s ease"
transform={`translateY(${openPerformerApplication ? 0 : "-70px"})`}
onClick={() =>
setOpenPerformerApplication(!openPerformerApplication)
}
zIndex={2002}
>
Close form
</Button>
<Box
ref={ref}
position="absolute"
top="12.5vh"
left={0}
height="75vh"
minH="75vh"
width="100vw"
sx={{
bg: "rgba(25,0,50,0.4)",
backdropFilter: "blur(7px)",
}}
boxShadow="0 0 30px rgba(0,0,0,0.8)"
opacity={onScreen ? 1 : 0}
transition="opacity 1.2s 0.8s ease-in-out"
zIndex={2001}
overflowY="scroll"
>
<AirtablePerformerInstance />
</Box>
</>
)}
{openSponsorApplication && (
<>
<Button
aria-label="Open the sponsor application form"
position="absolute"
bottom={{base: 10, md: 20}}
right={6}
colorScheme="pink"
bg="#FF61E6"
boxShadow="0 0 10px rgba(0, 0, 0, 0.6)"
size="sm"
transition="all 0.3s 0.8s ease"
transform={`translateY(${openSponsorApplication ? 0 : "-70px"})`}
onClick={() => setOpenSponsorApplication(!openSponsorApplication)}
zIndex={2002}
>
Close form
</Button>
<Box
ref={ref}
position="absolute"
top="12.5vh"
left={0}
height="75vh"
minH="75vh"
width="100vw"
sx={{
bg: "rgba(25,0,50,0.4)",
backdropFilter: "blur(7px)",
}}
boxShadow="0 0 30px rgba(0,0,0,0.8)"
opacity={onScreen ? 1 : 0}
transition="opacity 1.2s 0.8s ease-in-out"
zIndex={2001}
overflowY="scroll"
>
<AirtableSponsorInstance />
</Box>
</>
)}
</Box>
);
}
Example #10
Source File: playlists.js From grandcast.fm with Apache License 2.0 | 4 votes |
export default function Playlists() {
const { isSignedIn } = useAuth()
const [selectedPlaylist, setSelectedPlaylist] = useState('')
const [newPlaylist, setNewPlaylist] = useState('')
const { data } = useQuery(GET_PLAYLISTS)
const [createPlaylist] = useMutation(CREATE_PLAYLIST)
const filteredPlaylist = data?.playlists?.filter((p) => {
return p.name === selectedPlaylist
})[0]
return (
<Container>
{!isSignedIn() && <SignIn />}
{isSignedIn() && (
<div>
<FormControl id="playlists">
<Flex>
<Select
placeholder="Select playlist"
onChange={(e) => setSelectedPlaylist(e.target.value)}
>
{data?.playlists?.map((p) => {
return (
<option key={p.name} value={p.value}>
{p.name}
</option>
)
})}
</Select>
<Popover>
<PopoverTrigger>
<Button ml={4}>
<AddIcon />
</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Create new playlist</PopoverHeader>
<PopoverBody>
<FormControl id="newplaylist">
<Input
type="text"
onChange={(e) => setNewPlaylist(e.target.value)}
/>
<Button
mt={4}
onClick={() =>
createPlaylist({
variables: { playlistName: newPlaylist },
update: (proxy) => {
const data = proxy.readQuery({
query: GET_PLAYLISTS,
})
proxy.writeQuery({
query: GET_PLAYLISTS,
data: {
playlists: [
...data.playlists,
{
__typename: 'Playlist',
name: newPlaylist,
},
],
},
})
},
})
}
>
Create
</Button>
</FormControl>
</PopoverBody>
</PopoverContent>
</Popover>
</Flex>
</FormControl>
<VStack mt={4} spacing={4}>
{filteredPlaylist?.episodes?.map((e) => {
return (
<Episode key={e.id} episode={e} playlists={data.playlists} />
)
})}
</VStack>
</div>
)}
</Container>
)
}
Example #11
Source File: BuilderListView.jsx From scaffold-directory with MIT License | 4 votes |
export default function BuilderListView({ serverUrl, mainnetProvider, userRole }) {
const [builders, setBuilders] = useState([]);
const [isLoadingBuilders, setIsLoadingBuilders] = useState(false);
const { secondaryFontColor } = useCustomColorModes();
const isAdmin = userRole === USER_ROLES.admin;
const columns = useMemo(
() => [
{
Header: "Builder",
accessor: "builder",
disableSortBy: true,
Cell: ({ value }) => <BuilderAddressCell builderId={value} mainnetProvider={mainnetProvider} />,
},
{
Header: "Challenges",
accessor: "challenges",
sortDescFirst: true,
},
{
Header: "Socials",
accessor: "socials",
disableSortBy: true,
Cell: ({ value }) => <BuilderSocialLinksCell builder={value} isAdmin={isAdmin} />,
},
{
Header: "Last Activity",
accessor: "lastActivity",
sortDescFirst: true,
Cell: ({ value }) => <DateWithTooltip timestamp={value} />,
},
],
// eslint-disable-next-line
[userRole],
);
useEffect(() => {
async function fetchBuilders() {
setIsLoadingBuilders(true);
const fetchedBuilders = await axios.get(serverUrl + serverPath);
const processedBuilders = fetchedBuilders.data.map(builder => ({
builder: builder.id,
challenges: getAcceptedChallenges(builder?.challenges)?.length ?? 0,
socials: builder,
lastActivity: builderLastActivity(builder),
}));
setBuilders(processedBuilders);
setIsLoadingBuilders(false);
}
fetchBuilders();
}, [serverUrl]);
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data: builders,
initialState: { pageIndex: 0, pageSize: 25, sortBy: useMemo(() => [{ id: "lastActivity", desc: true }], []) },
},
useSortBy,
usePagination,
);
return (
<Container maxW="container.lg">
<Container maxW="container.md" centerContent>
<Heading as="h1" mb="4">
All Builders
</Heading>
<Text color={secondaryFontColor} textAlign="center" mb="10">
List of Ethereum builders creating products, prototypes, and tutorials with{" "}
<Link href="https://github.com/scaffold-eth/scaffold-eth" color="teal.500" isExternal>
scaffold-eth
</Link>
.
</Text>
</Container>
{isLoadingBuilders ? (
<BuilderListSkeleton />
) : (
<Box overflowX="auto" mb={8}>
<Center mb={5}>
<chakra.strong mr={2}>Total builders:</chakra.strong> {builders.length}
</Center>
<Table {...getTableProps()}>
<Thead>
{headerGroups.map(headerGroup => (
<Tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<Th {...column.getHeaderProps(column.getSortByToggleProps())}>
{column.render("Header")}
<chakra.span pl="4">
{column.isSorted ? (
column.isSortedDesc ? (
<TriangleDownIcon aria-label="sorted descending" />
) : (
<TriangleUpIcon aria-label="sorted ascending" />
)
) : null}
</chakra.span>
</Th>
))}
</Tr>
))}
</Thead>
<Tbody {...getTableBodyProps()}>
{page.map(row => {
prepareRow(row);
return (
<Tr {...row.getRowProps()}>
{row.cells.map(cell => (
<Td {...cell.getCellProps()}>{cell.render("Cell")}</Td>
))}
</Tr>
);
})}
</Tbody>
</Table>
<Center mt={4}>
<ButtonGroup>
<Button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
{"<<"}
</Button>
<Button onClick={() => previousPage()} disabled={!canPreviousPage}>
{"<"}
</Button>
<Button onClick={() => nextPage()} disabled={!canNextPage}>
{">"}
</Button>
<Button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
{">>"}
</Button>
</ButtonGroup>
</Center>
<Center mt={4}>
<Text mr={4}>
Page{" "}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{" "}
</Text>
<Box>
<Select
isFullWidth={false}
value={pageSize}
onChange={e => {
setPageSize(Number(e.target.value));
}}
>
{[25, 50, 100].map(pageSizeOption => (
<option key={pageSizeOption} value={pageSizeOption}>
Show {pageSizeOption}
</option>
))}
</Select>
</Box>
</Center>
</Box>
)}
</Container>
);
}
Example #12
Source File: BuilderProfileView.jsx From scaffold-directory with MIT License | 4 votes |
export default function BuilderProfileView({ serverUrl, mainnetProvider, address, userProvider, userRole }) {
const { builderAddress } = useParams();
const { primaryFontColor, secondaryFontColor, borderColor, iconBgColor } = useCustomColorModes();
const [builder, setBuilder] = useState();
const [challengeEvents, setChallengeEvents] = useState([]);
const [isLoadingBuilder, setIsLoadingBuilder] = useState(false);
const [isBuilderOnBg, setIsBuilderOnBg] = useState(false);
const [isLoadingTimestamps, setIsLoadingTimestamps] = useState(false);
const toast = useToast({ position: "top", isClosable: true });
const toastVariant = useColorModeValue("subtle", "solid");
const challenges = builder?.challenges ? Object.entries(builder.challenges) : undefined;
const acceptedChallenges = getAcceptedChallenges(builder?.challenges);
const isMyProfile = builderAddress === address;
const fetchBuilder = async () => {
setIsLoadingBuilder(true);
const fetchedBuilder = await axios.get(serverUrl + `/builders/${builderAddress}`);
setBuilder(fetchedBuilder.data);
try {
await axios.get(bgBackendUrl + `/builders/${builderAddress}`);
} catch (e) {
// Builder Not found in BG
setIsLoadingBuilder(false);
return;
}
setIsBuilderOnBg(true);
setIsLoadingBuilder(false);
};
useEffect(() => {
fetchBuilder();
// eslint-disable-next-line
}, [builderAddress]);
useEffect(() => {
if (!builderAddress) {
return;
}
async function fetchChallengeEvents() {
setIsLoadingTimestamps(true);
try {
const fetchedChallengeEvents = await getChallengeEventsForUser(builderAddress);
setChallengeEvents(fetchedChallengeEvents.sort(byTimestamp).reverse());
setIsLoadingTimestamps(false);
} catch (error) {
toast({
description: "Can't get challenges metadata. Please try again",
status: "error",
variant: toastVariant,
});
}
}
fetchChallengeEvents();
// eslint-disable-next-line
}, [builderAddress]);
return (
<Container maxW="container.xl">
<SimpleGrid gap={14} columns={{ base: 1, xl: 4 }}>
<GridItem colSpan={1}>
<BuilderProfileCard
builder={builder}
mainnetProvider={mainnetProvider}
isMyProfile={isMyProfile}
userProvider={userProvider}
fetchBuilder={fetchBuilder}
userRole={userRole}
/>
</GridItem>
{isBuilderOnBg ? (
<GridItem colSpan={{ base: 1, xl: 3 }}>
<Box borderColor={borderColor} borderWidth={1} p={5}>
<Flex direction="column" align="center" justify="center">
<Image src="/assets/bg.png" mb={3} />
<Text mb={3} fontSize="lg" fontWeight="bold">
This builder has upgraded to BuidlGuidl.
</Text>
<Button as={Link} href={`${BG_FRONTEND_URL}/builders/${builderAddress}`} isExternal colorScheme="blue">
View their profile on Buidlguidl
</Button>
</Flex>
</Box>
</GridItem>
) : (
<GridItem colSpan={{ base: 1, xl: 3 }}>
<HStack spacing={4} mb={8}>
<Flex borderRadius="lg" borderColor={borderColor} borderWidth={1} p={4} w="full" justify="space-between">
<Flex bg={iconBgColor} borderRadius="lg" w={12} h={12} justify="center" align="center">
<InfoOutlineIcon w={5} h={5} />
</Flex>
<div>
<Text fontSize="xl" fontWeight="medium" textAlign="right">
{acceptedChallenges.length}
</Text>
<Text fontSize="sm" color={secondaryFontColor} textAlign="right">
challenges completed
</Text>
</div>
</Flex>
<Flex borderRadius="lg" borderColor={borderColor} borderWidth={1} p={4} w="full" justify="space-between">
<Flex bg={iconBgColor} borderRadius="lg" w={12} h={12} justify="center" align="center">
<InfoOutlineIcon w={5} h={5} />
</Flex>
<div>
<Text fontSize="xl" fontWeight="medium" textAlign="right">
{builder?.function ? (
<Tag colorScheme={userFunctionDescription[builder?.function].colorScheme} variant="solid">
{userFunctionDescription[builder?.function].label}
</Tag>
) : (
"-"
)}
</Text>
<Text fontSize="sm" color={secondaryFontColor} textAlign="right">
Role
</Text>
</div>
</Flex>
</HStack>
<Flex mb={4}>
<Text fontSize="2xl" fontWeight="bold">
Challenges
</Text>
<Spacer />
</Flex>
{isLoadingBuilder && <BuilderProfileChallengesTableSkeleton />}
{!isLoadingBuilder &&
(challenges ? (
<Box overflowX="auto">
<Table>
{isMyProfile && (
<TableCaption>
<Button as={RouteLink} colorScheme="blue" to="/">
Start a challenge
</Button>
</TableCaption>
)}
<Thead>
<Tr>
<Th>Name</Th>
<Th>Contract</Th>
<Th>Live Demo</Th>
<Th>Updated</Th>
<Th>Status</Th>
</Tr>
</Thead>
<Tbody>
{challenges.map(([challengeId, lastSubmission]) => {
if (!challengeInfo[challengeId]) {
return null;
}
const lastEventForChallenge = challengeEvents.filter(
event => event.payload.challengeId === challengeId,
)[0];
return (
<Tr key={challengeId}>
<Td>
<Link as={RouteLink} to={`/challenge/${challengeId}`} fontWeight="700" color="teal.500">
{challengeInfo[challengeId].label}
</Link>
</Td>
<Td>
<Link
// Legacy branchUrl
href={lastSubmission.contractUrl || lastSubmission.branchUrl}
color="teal.500"
target="_blank"
rel="noopener noreferrer"
>
Code
</Link>
</Td>
<Td>
<Link
href={lastSubmission.deployedUrl}
color="teal.500"
target="_blank"
rel="noopener noreferrer"
>
Demo
</Link>
</Td>
<Td>
{isLoadingTimestamps ? (
<SkeletonText noOfLines={1} />
) : (
<DateWithTooltip timestamp={lastEventForChallenge?.timestamp} />
)}
</Td>
<Td>
<ChallengeStatusTag
status={lastSubmission.status}
comment={lastSubmission.reviewComment}
autograding={lastSubmission.autograding}
/>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</Box>
) : (
<Flex
justify="center"
align="center"
borderRadius="lg"
borderColor={borderColor}
borderWidth={1}
py={36}
w="full"
>
{isMyProfile ? (
<Box maxW="xs" textAlign="center">
<Text fontWeight="medium" color={primaryFontColor} mb={2}>
Start a new challenge
</Text>
<Text color={secondaryFontColor} mb={4}>
Show off your skills. Learn everything you need to build on Ethereum!
</Text>
<Button as={RouteLink} colorScheme="blue" to="/">
Start a challenge
</Button>
</Box>
) : (
<Box maxW="xs" textAlign="center">
<Text color={secondaryFontColor} mb={4}>
This builder hasn't completed any challenges.
</Text>
</Box>
)}
</Flex>
))}
</GridItem>
)}
</SimpleGrid>
</Container>
);
}
Example #13
Source File: ChallengeDetailView.jsx From scaffold-directory with MIT License | 4 votes |
export default function ChallengeDetailView({ serverUrl, address, userProvider, userRole, loadWeb3Modal }) {
const [descriptionJs, setDescriptionJs] = useState(null);
const [descriptionTs, setDescriptionTs] = useState(null);
const { challengeId } = useParams();
const history = useHistory();
const { isOpen, onOpen, onClose } = useDisclosure();
const [openModalOnLoad, setOpenModalOnLoad] = useState(false);
const challenge = challengeInfo[challengeId];
const isWalletConnected = !!userRole;
const isAnonymous = userRole && USER_ROLES.anonymous === userRole;
// Fetch challenge description from local files.
// In the future, this might be a fetch to the repos/branchs README
// (Ideally fetched at build time)
useEffect(() => {
getChallengeReadme(challengeId, "js")
.then(text => setDescriptionJs(parseGithubReadme(text)))
.catch(() => setDescriptionJs(challenge.description));
getChallengeReadme(challengeId, "ts")
.then(text => setDescriptionTs(parseGithubReadme(text)))
.catch(() => setDescriptionTs(challenge.description));
}, [challengeId, challenge]);
useEffect(() => {
if (!isWalletConnected || isAnonymous) return;
if (openModalOnLoad) {
onOpen();
setOpenModalOnLoad(false);
}
}, [isAnonymous, isWalletConnected, onOpen, userRole, openModalOnLoad, setOpenModalOnLoad]);
if (!challenge) {
// TODO implement a 404 page
// this looks good: https://ant.design/components/result/#components-result-demo-404
history.push("/404");
}
const handleSubmitChallengeModal = async () => {
if (isWalletConnected && !isAnonymous) {
return onOpen();
}
if (!isWalletConnected) {
await loadWeb3Modal();
setOpenModalOnLoad(true);
}
};
const challengeActionButtons = (type = "JS") => {
const repo = type === "JS" ? JS_CHALLENGE_REPO : TS_CHALLENGE_REPO;
return (
<Box>
<Button
as="a"
colorScheme="gray"
variant="outline"
href={`${repo}/tree/${challenge.branchName}`}
target="_blank"
rel="noopener noreferrer"
>
View it on Github <ExternalLinkIcon ml={1} />
</Button>
<Box pos="fixed" bottom={0} p={6} left={0} right={0}>
<Tooltip label={isAnonymous ? "You need to register as a builder" : "Submit Challenge"} shouldWrapChildren>
<Button colorScheme="blue" boxShadow="dark-lg" onClick={handleSubmitChallengeModal} disabled={isAnonymous}>
Submit challenge
</Button>
</Tooltip>
</Box>
</Box>
);
};
return (
// Magic number for maxW to match GitHub
<Container maxW="894px" mb="60px">
<Box textAlign="center" mb={6}>
<Heading as="h1" mb={4}>
{challenge.label}
</Heading>
</Box>
<Tabs variant="enclosed-colored" align="center">
<TabList>
<Tab>Javascript</Tab>
<Tab>Typescript</Tab>
</TabList>
<TabPanels align="left">
<TabPanel>
<SkeletonText mt="4" noOfLines={4} spacing="4" isLoaded={descriptionJs} />
<ReactMarkdown components={ChakraUIRenderer(chakraMarkdownComponents)}>{descriptionJs}</ReactMarkdown>
<Box textAlign="center" my={6}>
{challengeActionButtons("JS")}
</Box>
</TabPanel>
<TabPanel>
<SkeletonText mt="4" noOfLines={4} spacing="4" isLoaded={descriptionTs} />
<ReactMarkdown components={ChakraUIRenderer(chakraMarkdownComponents)}>{descriptionTs}</ReactMarkdown>
<Box textAlign="center" my={6}>
{challengeActionButtons("TS")}
</Box>
</TabPanel>
</TabPanels>
</Tabs>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Submit Challenge</ModalHeader>
<ModalCloseButton />
<ModalBody px={6} pb={8}>
<ChallengeSubmission
challenge={challenge}
serverUrl={serverUrl}
address={address}
userProvider={userProvider}
loadWeb3Modal={loadWeb3Modal}
/>
</ModalBody>
</ModalContent>
</Modal>
</Container>
);
}
Example #14
Source File: HomeView.jsx From scaffold-directory with MIT License | 4 votes |
export default function HomeView({ connectedBuilder }) {
const { primaryFontColor } = useCustomColorModes();
const builderAttemptedChallenges = useMemo(() => {
if (!connectedBuilder?.challenges) {
return [];
}
return Object.fromEntries(
Object.entries(connectedBuilder.challenges).filter(([_, challengeData]) => challengeData?.status),
);
}, [connectedBuilder]);
return (
<Container maxW="container.lg" centerContent>
<div style={{ maxWidth: 740, margin: "auto", border: "1px solid #DDDDDD", padding: 32, marginBottom: 64 }}>
<Text color={primaryFontColor} mb="6" fontSize="xl" textAlign="center">
<span role="img" aria-label="teacher icon">
??
</span>{" "}
Learn how to build on Ethereum; the superpowers and the gotchas.
</Text>
<Text color={primaryFontColor} mb="6" fontSize="xl" textAlign="center">
<span role="img" aria-label="teacher icon">
?
</span>{" "}
Watch this quick video as an{" "}
<a
href="https://www.youtube.com/watch?v=MlJPjJQZtC8"
target="_blank"
rel="noopener noreferrer"
style={{ textDecoration: "underline" }}
>
Intro to Ethereum Development
</a>
.
</Text>
<Text color={primaryFontColor} mb="2" fontSize="xl" textAlign="center">
Then use{" "}
<a
style={{ textDecoration: "underline" }}
href="https://github.com/scaffold-eth/scaffold-eth#-scaffold-eth"
rel="noopener noreferrer"
target="_blank"
>
<span role="img" aria-label="teacher icon">
?
</span>{" "}
Scaffold-ETH
</a>{" "}
to copy/paste each Solidity concept and tinker:
</Text>
<Text color={primaryFontColor} mb="8" fontSize="xl" textAlign="center">
<div>
<a
href="https://docs.soliditylang.org/en/v0.6.6/units-and-global-variables.html"
target="_blank"
rel="noopener noreferrer"
>
global units
</a>
,{" "}
<a target="_blank" href="https://solidity-by-example.org/primitives/" rel="noopener noreferrer">
primitives
</a>
,{" "}
<a target="_blank" href="https://solidity-by-example.org/mapping/" rel="noopener noreferrer">
mappings
</a>
,{" "}
<a href="https://solidity-by-example.org/structs/" target="_blank" rel="noopener noreferrer">
structs
</a>
,{" "}
<a href="https://solidity-by-example.org/function-modifier/" target="_blank" rel="noopener noreferrer">
modifiers
</a>
,{" "}
<a href="https://solidity-by-example.org/events/" target="_blank" rel="noopener noreferrer">
events
</a>
,
</div>{" "}
<a href="https://solidity-by-example.org/inheritance/" target="_blank" rel="noopener noreferrer">
inheritance
</a>
,{" "}
<a href="https://solidity-by-example.org/sending-ether/" target="_blank" rel="noopener noreferrer">
sending eth
</a>
, and{" "}
<a href="https://solidity-by-example.org/payable/" target="_blank" rel="noopener noreferrer">
payable
</a>
/
<a href="https://solidity-by-example.org/fallback/" target="_blank" rel="noopener noreferrer">
fallback
</a>{" "}
functions.
</Text>
<Text color={primaryFontColor} mb="0" fontSize="xl" textAlign="center">
<span role="img" aria-label="teacher icon">
??
</span>{" "}
When you are ready to test your knowledge, speed run Ethereum:
</Text>
</div>
<Box>
{Object.entries(challengeInfo).map(([challengeId, challenge], index) => (
<ChallengeExpandedCard
challengeId={challengeId}
challenge={challenge}
challengeIndex={index}
builderAttemptedChallenges={builderAttemptedChallenges}
/>
))}
</Box>
</Container>
);
}
Example #15
Source File: SubmissionReviewView.jsx From scaffold-directory with MIT License | 4 votes |
export default function SubmissionReviewView({ userProvider }) {
const address = useUserAddress(userProvider);
const [challenges, setChallenges] = React.useState([]);
const [isLoadingChallenges, setIsLoadingChallenges] = React.useState(true);
const [draftBuilds, setDraftBuilds] = React.useState([]);
const [isLoadingDraftBuilds, setIsLoadingDraftBuilds] = React.useState(true);
const toast = useToast({ position: "top", isClosable: true });
const toastVariant = useColorModeValue("subtle", "solid");
const { secondaryFontColor } = useCustomColorModes();
const fetchSubmittedChallenges = useCallback(async () => {
setIsLoadingChallenges(true);
let fetchedChallenges;
try {
fetchedChallenges = await getSubmittedChallenges(address);
} catch (error) {
toast({
description: "There was an error getting the submitted challenges. Please try again",
status: "error",
variant: toastVariant,
});
setIsLoadingChallenges(false);
return;
}
setChallenges(fetchedChallenges.sort(bySubmittedTimestamp));
setIsLoadingChallenges(false);
}, [address, toastVariant, toast]);
const fetchSubmittedBuilds = useCallback(async () => {
setIsLoadingDraftBuilds(true);
let fetchedDraftBuilds;
try {
fetchedDraftBuilds = await getDraftBuilds(address);
} catch (error) {
toast({
description: "There was an error getting the draft builds. Please try again",
status: "error",
variant: toastVariant,
});
setIsLoadingDraftBuilds(false);
return;
}
setDraftBuilds(fetchedDraftBuilds.sort(bySubmittedTimestamp));
setIsLoadingDraftBuilds(false);
}, [address, toastVariant, toast]);
useEffect(() => {
if (!address) {
return;
}
fetchSubmittedChallenges();
// eslint-disable-next-line
}, [address]);
useEffect(() => {
if (!address) {
return;
}
fetchSubmittedBuilds();
// eslint-disable-next-line
}, [address]);
const handleSendChallengeReview = reviewType => async (userAddress, challengeId, comment) => {
let signMessage;
try {
signMessage = await getChallengeReviewSignMessage(address, userAddress, challengeId, reviewType);
} catch (error) {
toast({
description: " Sorry, the server is overloaded. ???",
status: "error",
variant: toastVariant,
});
return;
}
let signature;
try {
signature = await userProvider.send("personal_sign", [signMessage, address]);
} catch (error) {
toast({
description: "Couldn't get a signature from the Wallet",
status: "error",
variant: toastVariant,
});
console.error(error);
return;
}
try {
await patchChallengeReview(address, signature, { userAddress, challengeId, newStatus: reviewType, comment });
} catch (error) {
if (error.status === 401) {
toast({
status: "error",
description: "Submission Error. You don't have the required role.",
variant: toastVariant,
});
return;
}
toast({
status: "error",
description: "Submission Error. Please try again.",
variant: toastVariant,
});
return;
}
toast({
description: "Review submitted successfully",
status: "success",
variant: toastVariant,
});
fetchSubmittedChallenges();
};
const handleSendBuildReview = reviewType => async (userAddress, buildId) => {
let signMessage;
try {
signMessage = await getBuildReviewSignMessage(address, buildId, reviewType);
} catch (error) {
toast({
description: " Sorry, the server is overloaded. ???",
status: "error",
variant: toastVariant,
});
return;
}
let signature;
try {
signature = await userProvider.send("personal_sign", [signMessage, address]);
} catch (error) {
toast({
description: "Couldn't get a signature from the Wallet",
status: "error",
variant: toastVariant,
});
return;
}
try {
await patchBuildReview(address, signature, { userAddress, buildId, newStatus: reviewType });
} catch (error) {
if (error.status === 401) {
toast({
status: "error",
description: "Submission Error. You don't have the required role.",
variant: toastVariant,
});
return;
}
toast({
status: "error",
description: "Submission Error. Please try again.",
variant: toastVariant,
});
return;
}
toast({
description: "Review submitted successfully",
status: "success",
variant: toastVariant,
});
fetchSubmittedBuilds();
};
return (
<Container maxW="container.lg">
<Container maxW="container.md" centerContent>
<Heading as="h1">Review Submissions</Heading>
<Text color={secondaryFontColor}>Pending submissions to validate.</Text>
<Text color={secondaryFontColor} mb="6">
Check our{" "}
<Link href={RUBRIC_URL} color="teal.500" isExternal>
Grading Rubric
</Link>
.
</Text>
</Container>
<Heading as="h2" size="lg" mt={6} mb={4}>
Challenges
</Heading>
<Box overflowX="auto">
{isLoadingChallenges ? (
<ChallengesTableSkeleton />
) : (
<Table>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Challenge</Th>
<Th>Submitted time</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{!challenges || challenges.length === 0 ? (
<Tr>
<Td colSpan={6}>
<Text color={secondaryFontColor} textAlign="center" mb={4}>
<Icon as={HeroIconInbox} w={6} h={6} color={secondaryFontColor} mt={6} mb={4} />
<br />
All challenges have been reviewed
</Text>
</Td>
</Tr>
) : (
challenges.map(challenge => (
<ChallengeReviewRow
key={`${challenge.userAddress}_${challenge.id}`}
challenge={challenge}
isLoading={isLoadingChallenges}
approveClick={handleSendChallengeReview("ACCEPTED")}
rejectClick={handleSendChallengeReview("REJECTED")}
userProvider={userProvider}
/>
))
)}
</Tbody>
</Table>
)}
</Box>
<Heading as="h2" size="lg" mt={6} mb={4}>
Builds
</Heading>
<Box overflowX="auto">
{isLoadingDraftBuilds ? (
<BuildsTableSkeleton />
) : (
<Table mb={4}>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Build Name</Th>
<Th>Description</Th>
<Th>Branch URL</Th>
<Th>Submitted time</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{!draftBuilds || draftBuilds.length === 0 ? (
<Tr>
<Td colSpan={5}>
<Text color={secondaryFontColor} textAlign="center" mb={4}>
<Icon as={HeroIconInbox} w={6} h={6} color={secondaryFontColor} mt={6} mb={4} />
<br />
All builds have been reviewed
</Text>
</Td>
</Tr>
) : (
draftBuilds.map(build => (
<BuildReviewRow
key={`${build.userAddress}_${build.id}`}
build={build}
isLoading={isLoadingDraftBuilds}
approveClick={handleSendBuildReview("ACCEPTED")}
rejectClick={handleSendBuildReview("REJECTED")}
/>
))
)}
</Tbody>
</Table>
)}
</Box>
</Container>
);
}
Example #16
Source File: index.js From handsign-tensorflow with BSD 2-Clause "Simplified" License | 4 votes |
export default function Home() {
const webcamRef = useRef(null)
const canvasRef = useRef(null)
const [camState, setCamState] = useState("on")
const [sign, setSign] = useState(null)
let signList = []
let currentSign = 0
let gamestate = "started"
// let net;
async function runHandpose() {
const net = await handpose.load()
_signList()
// window.requestAnimationFrame(loop);
setInterval(() => {
detect(net)
}, 150)
}
function _signList() {
signList = generateSigns()
}
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
;[a[i], a[j]] = [a[j], a[i]]
}
return a
}
function generateSigns() {
const password = shuffle(Signpass)
return password
}
async function detect(net) {
// Check data is available
if (
typeof webcamRef.current !== "undefined" &&
webcamRef.current !== null &&
webcamRef.current.video.readyState === 4
) {
// Get Video Properties
const video = webcamRef.current.video
const videoWidth = webcamRef.current.video.videoWidth
const videoHeight = webcamRef.current.video.videoHeight
// Set video width
webcamRef.current.video.width = videoWidth
webcamRef.current.video.height = videoHeight
// Set canvas height and width
canvasRef.current.width = videoWidth
canvasRef.current.height = videoHeight
// Make Detections
const hand = await net.estimateHands(video)
if (hand.length > 0) {
//loading the fingerpose model
const GE = new fp.GestureEstimator([
fp.Gestures.ThumbsUpGesture,
Handsigns.aSign,
Handsigns.bSign,
Handsigns.cSign,
Handsigns.dSign,
Handsigns.eSign,
Handsigns.fSign,
Handsigns.gSign,
Handsigns.hSign,
Handsigns.iSign,
Handsigns.jSign,
Handsigns.kSign,
Handsigns.lSign,
Handsigns.mSign,
Handsigns.nSign,
Handsigns.oSign,
Handsigns.pSign,
Handsigns.qSign,
Handsigns.rSign,
Handsigns.sSign,
Handsigns.tSign,
Handsigns.uSign,
Handsigns.vSign,
Handsigns.wSign,
Handsigns.xSign,
Handsigns.ySign,
Handsigns.zSign,
])
const estimatedGestures = await GE.estimate(hand[0].landmarks, 6.5)
// document.querySelector('.pose-data').innerHTML =JSON.stringify(estimatedGestures.poseData, null, 2);
if (gamestate === "started") {
document.querySelector("#app-title").innerText =
"Make a ? gesture with your hand to start"
}
if (
estimatedGestures.gestures !== undefined &&
estimatedGestures.gestures.length > 0
) {
const confidence = estimatedGestures.gestures.map(p => p.confidence)
const maxConfidence = confidence.indexOf(
Math.max.apply(undefined, confidence)
)
//setting up game state, looking for thumb emoji
if (
estimatedGestures.gestures[maxConfidence].name === "thumbs_up" &&
gamestate !== "played"
) {
_signList()
gamestate = "played"
document.getElementById("emojimage").classList.add("play")
document.querySelector(".tutor-text").innerText =
"make a hand gesture based on letter shown below"
} else if (gamestate === "played") {
document.querySelector("#app-title").innerText = ""
//looping the sign list
if (currentSign === signList.length) {
_signList()
currentSign = 0
return
}
// console.log(signList[currentSign].src.src)
//game play state
if (
typeof signList[currentSign].src.src === "string" ||
signList[currentSign].src.src instanceof String
) {
document
.getElementById("emojimage")
.setAttribute("src", signList[currentSign].src.src)
if (
signList[currentSign].alt ===
estimatedGestures.gestures[maxConfidence].name
) {
currentSign++
}
setSign(estimatedGestures.gestures[maxConfidence].name)
}
} else if (gamestate === "finished") {
return
}
}
}
// Draw hand lines
const ctx = canvasRef.current.getContext("2d")
drawHand(hand, ctx)
}
}
// if (sign) {
// console.log(sign, Signimage[sign])
// }
useEffect(() => {
runHandpose()
}, [])
function turnOffCamera() {
if (camState === "on") {
setCamState("off")
} else {
setCamState("on")
}
}
return (
<ChakraProvider>
<Metatags />
<Box bgColor="#5784BA">
<Container centerContent maxW="xl" height="100vh" pt="0" pb="0">
<VStack spacing={4} align="center">
<Box h="20px"></Box>
<Heading
as="h3"
size="md"
className="tutor-text"
color="white"
textAlign="center"
></Heading>
<Box h="20px"></Box>
</VStack>
<Heading
as="h1"
size="lg"
id="app-title"
color="white"
textAlign="center"
>
?♀️ Loading the Magic ?♂️
</Heading>
<Box id="webcam-container">
{camState === "on" ? (
<Webcam id="webcam" ref={webcamRef} />
) : (
<div id="webcam" background="black"></div>
)}
{sign ? (
<div
style={{
position: "absolute",
marginLeft: "auto",
marginRight: "auto",
right: "calc(50% - 50px)",
bottom: 100,
textAlign: "-webkit-center",
}}
>
<Text color="white" fontSize="sm" mb={1}>
detected gestures
</Text>
<img
alt="signImage"
src={
Signimage[sign]?.src
? Signimage[sign].src
: "/loveyou_emoji.svg"
}
style={{
height: 30,
}}
/>
</div>
) : (
" "
)}
</Box>
<canvas id="gesture-canvas" ref={canvasRef} style={{}} />
<Box
id="singmoji"
style={{
zIndex: 9,
position: "fixed",
top: "50px",
right: "30px",
}}
></Box>
<Image h="150px" objectFit="cover" id="emojimage" />
{/* <pre className="pose-data" color="white" style={{position: 'fixed', top: '150px', left: '10px'}} >Pose data</pre> */}
</Container>
<Stack id="start-button" spacing={4} direction="row" align="center">
<Button
leftIcon={
camState === "on" ? (
<RiCameraFill size={20} />
) : (
<RiCameraOffFill size={20} />
)
}
onClick={turnOffCamera}
colorScheme="orange"
>
Camera
</Button>
<About />
</Stack>
</Box>
</ChakraProvider>
)
}