@chakra-ui/react#ModalContent TypeScript Examples
The following examples show how to use
@chakra-ui/react#ModalContent.
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: receiving-call-modal.tsx From video-chat with MIT License | 6 votes |
export function ReceivingCallOverlay(props: Props){
if (!props.calling) return <></>
return(
<Modal isOpen={props.calling} isCentered onClose={() => {}}>
<ModalOverlay>
<ModalContent
p="16"
backgroundColor="gray.800"
alignItems="center"
justifyContent="center"
display="flex"
flexDirection="column"
>
<ModalHeader color="white">{props.caller} is calling you</ModalHeader>
<ModalBody display="flex" alignItems="center" justifyContent="space-evenly" w="full">
<Button colorScheme="green" onClick={props.answer}>Answer call</Button>
<Button colorScheme="red" onClick={props.refuse}>Refuse call</Button>
</ModalBody>
</ModalContent>
</ModalOverlay>
</Modal>
)
}
Example #2
Source File: note-modal.tsx From notebook with MIT License | 6 votes |
NoteModal: React.SFC<NoteFormProps> = ({
isOpen,
onClose,
selectedNote
}) => {
return (
<AnimatePresence>
<motion.div layoutId={selectedNote?.id}>
<Modal
isOpen={isOpen}
onClose={onClose}
scrollBehavior={"inside"}
isCentered
motionPreset="slideInBottom"
>
<ModalOverlay />
<ModalContent>
<motion.div>
<ModalHeader isTruncated paddingRight="10">
{selectedNote?.title}
</ModalHeader>
</motion.div>
<ModalCloseButton />
<motion.div>
<ModalBody pb={6}>{selectedNote?.body}</ModalBody>
</motion.div>
</ModalContent>
</Modal>
</motion.div>
</AnimatePresence>
);
}
Example #3
Source File: index.tsx From rari-dApp with GNU Affero General Public License v3.0 | 6 votes |
DepositModal = (props: Props) => {
return (
<Modal
motionPreset="slideInBottom"
isOpen={props.isOpen}
onClose={props.onClose}
isCentered
>
<ModalOverlay />
<ModalContent
{...MODAL_PROPS}
height={{
md: requiresSFIStaking(props.trancheRating) ? "380px" : "295px",
base: requiresSFIStaking(props.trancheRating) ? "390px" : "310px",
}}
>
<AmountSelect
onClose={props.onClose}
tranchePool={props.tranchePool}
trancheRating={props.trancheRating}
/>
</ModalContent>
</Modal>
);
}
Example #4
Source File: Modal.tsx From calories-in with MIT License | 6 votes |
function Modal({ isOpen, onClose }: Props) {
const selectRef = useRef<HTMLSelectElement>(null)
return (
<ModalBase isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Filters</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Content selectRef={selectRef} />
</ModalBody>
<ModalFooter>
<Footer onClose={onClose} />
</ModalFooter>
</ModalContent>
</ModalBase>
)
}
Example #5
Source File: MissingFoodsModal.tsx From calories-in with MIT License | 6 votes |
function MissingFoodsModal({ isOpen, onClose, onImport }: Props) {
return (
<Modal isOpen={isOpen} onClose={onClose} size="md" isCentered>
<ModalOverlay />
<ModalContent>
<ModalHeader>Missing foods</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Text fontWeight="medium">
The meal plan you contains foods that are not part of your list.
</Text>
<br />
<Text>
You can try to import the missing foods or continue without them.
</Text>
</ModalBody>
<ModalFooter>
<Button onClick={onClose} mr={3}>
Continue
</Button>
<Button
variant="solid"
colorScheme="teal"
onClick={() => {
onImport()
onClose()
}}
>
Import foods
</Button>
</ModalFooter>
</ModalContent>
</Modal>
)
}
Example #6
Source File: DeleteConfirmationModal.tsx From calories-in with MIT License | 6 votes |
function DeleteConfirmationModal({
isOpen,
onCancel,
onConfirm,
text,
confirmButtonLabel,
}: Props) {
return (
<Modal isOpen={isOpen} onClose={onCancel} size="xs" isCentered>
<ModalOverlay />
<ModalContent>
<ModalHeader>Delete food</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Text>{text}</Text>
<br />
<Text fontWeight="medium">This action cannot be undone.</Text>
</ModalBody>
<ModalFooter>
<Button variant="outline" onClick={onCancel}>
Cancel
</Button>
<Button colorScheme="red" ml={3} onClick={onConfirm}>
{confirmButtonLabel}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
)
}
Example #7
Source File: index.tsx From rari-dApp with GNU Affero General Public License v3.0 | 6 votes |
DepositModal = (props: Props) => {
const [currentScreen, setCurrentScreen] = useState(CurrentScreen.MAIN);
const [mode, setMode] = useState(Mode.DEPOSIT);
return (
<Modal
motionPreset="slideInBottom"
isOpen={props.isOpen}
onClose={props.onClose}
isCentered
>
<ModalOverlay />
<ModalContent {...MODAL_PROPS} height="300px">
{currentScreen === CurrentScreen.MAIN ? (
<AmountSelect
onClose={props.onClose}
openOptions={() => setCurrentScreen(CurrentScreen.OPTIONS)}
mode={mode}
/>
) : (
<OptionsMenu
onClose={() => setCurrentScreen(CurrentScreen.MAIN)}
onSetMode={setMode}
mode={mode}
/>
)}
</ModalContent>
</Modal>
);
}
Example #8
Source File: index.tsx From rari-dApp with GNU Affero General Public License v3.0 | 6 votes |
DepositModal = (props: Props) => {
const [mode, setMode] = useState(props.defaultMode);
useEffect(() => {
setMode(props.defaultMode);
}, [props.isOpen, props.defaultMode]);
return (
<Modal
motionPreset="slideInBottom"
isOpen={props.isOpen}
onClose={props.onClose}
isCentered
>
<ModalOverlay />
<ModalContent {...MODAL_PROPS}>
<AmountSelect
comptrollerAddress={props.comptrollerAddress}
onClose={props.onClose}
assets={props.assets}
index={props.index}
mode={mode}
setMode={setMode}
isBorrowPaused={props.isBorrowPaused}
/>
</ModalContent>
</Modal>
);
}
Example #9
Source File: AuthModal.tsx From coindrop with GNU General Public License v3.0 | 5 votes |
AuthModal: FunctionComponent<Props> = ({ isOpen }) => {
const router = useRouter();
const onClose = () => router.push('/', undefined, { shallow: true });
return (
<Modal
id="auth-modal"
isOpen={isOpen}
onClose={onClose}
>
<ModalOverlay />
<ModalContent>
<ModalHeader textAlign="center" mb={-3}>Sign in to continue</ModalHeader>
<ModalCloseButton />
<ModalBody>
<FirebaseAuth />
<Text textAlign="center" fontSize="xs" mb={2}>
{'If you\'re having trouble logging in, please try again with '}
<Link
href="https://www.google.com/chrome/"
target="_blank"
rel="noreferrer"
textDecoration="underline"
>
Chrome
</Link>
{' or '}
<Link
href="https://www.mozilla.org/firefox"
target="_blank"
rel="noreferrer"
textDecoration="underline"
>
Firefox
</Link>
.
</Text>
</ModalBody>
</ModalContent>
</Modal>
);
}
Example #10
Source File: Content.tsx From calories-in with MIT License | 5 votes |
function Content({ title, onClose, initialRef, variantFormIndex }: Props) {
const { register } = useFormContext()
const nameRegister = register('name')
const nameInputRef = useMergeRefs(nameRegister.ref, initialRef)
const onSubmit = useSubmitVariantNameForm({
variantFormIndex,
onComplete: onClose,
})
const { errorMessage, isInvalid } = useFormError('name')
useSelectInputText(initialRef)
return (
<form onSubmit={onSubmit}>
<ModalContent>
<ModalHeader>{title}</ModalHeader>
<ModalCloseButton />
<ModalBody>
<FormControl isInvalid={isInvalid}>
<FormLabel>Name</FormLabel>
<Input
autoComplete="off"
{...nameRegister}
ref={nameInputRef}
focusBorderColor={isInvalid ? 'red.500' : undefined}
placeholder="Enter name"
/>
<Collapse animateOpacity={true} in={Boolean(errorMessage)}>
<Box minHeight="21px">
<FormErrorMessage>{errorMessage}</FormErrorMessage>
</Box>
</Collapse>
</FormControl>
</ModalBody>
<ModalFooter>
<Button mr={3} onClick={onClose}>
Close
</Button>
<Button
type="submit"
colorScheme="teal"
variant="solid"
onClick={onSubmit}
>
Rename
</Button>
</ModalFooter>
</ModalContent>
</form>
)
}
Example #11
Source File: ShareButtonModal.tsx From coindrop with GNU General Public License v3.0 | 5 votes |
ShareButtonModal: FunctionComponent<Props> = ({ buttonColor }) => {
const { isOpen, onClose, onOpen } = useDisclosure();
const { query: { piggybankName: piggybankNameQuery }} = useRouter();
const piggybankName = Array.isArray(piggybankNameQuery) ? piggybankNameQuery[0] : piggybankNameQuery;
const publicUrl = `coindrop.to/${piggybankName}`;
const fullPublicUrl = `https://${publicUrl}`;
return (
<>
<Button
leftIcon={<ShareIcon />}
onClick={onOpen}
colorScheme={buttonColor}
isDisabled={isOpen}
>
Share
</Button>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalCloseButton />
<Heading
mt={4}
as="h2"
size="md"
mx={12}
textAlign="center"
>
{publicUrl}
</Heading>
<ModalBody>
<Box mb={4}>
<Box>
<Heading as="h2" size="lg">
Link
</Heading>
</Box>
<Center mt={2}>
<CopyLinkShareButton textToCopy={publicUrl} />
</Center>
</Box>
<ShareEmbedButton
fullPublicUrl={fullPublicUrl}
/>
<PiggybankQRCode
fullPublicUrl={fullPublicUrl}
publicUrl={publicUrl}
/>
<TipCards />
</ModalBody>
<ModalFooter />
</ModalContent>
</Modal>
</>
);
}
Example #12
Source File: PaymentMethodButtonModal.tsx From coindrop with GNU General Public License v3.0 | 5 votes |
PaymentMethodButtonModal: FunctionComponent<Props> = ({ isOpen, onClose, paymentMethod, paymentMethodDisplayName, paymentMethodValue }) => {
const { onCopy, hasCopied } = useClipboard(paymentMethodValue);
const { piggybankDbData } = useContext(PublicPiggybankDataContext);
const { name } = piggybankDbData;
const Icon = paymentMethodIcons[paymentMethod];
const addressIsUrl = isUrl(paymentMethodValue, {
require_protocol: true,
require_valid_protocol: true,
protocols: ['http', 'https'],
allow_protocol_relative_urls: false,
});
return (
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent mx={6}>
<ModalHeader
textAlign="center"
mt={3}
mx="auto"
>
{name}
{"'s "}
{paymentMethodDisplayName}
{' address'}
</ModalHeader>
<ModalCloseButton />
<ModalBody
pt={0}
mb={3}
mx="auto"
>
<Flex justify="center" align="center">
<Icon
mr={2}
boxSize="48px"
/>
<Text
wordBreak="break-all"
textAlign="center"
>
{paymentMethodValue}
</Text>
</Flex>
<Flex
my={2}
align="center"
justify="center"
>
{addressIsUrl ? (
<Link href={paymentMethodValue} isExternal>
<Button
leftIcon={<ExternalLinkIcon />}
href={paymentMethodValue}
mr={2}
>
Open
</Button>
</Link>
) : (
<Button
leftIcon={hasCopied ? <CheckIcon /> : <CopyIcon />}
onClick={onCopy}
>
{hasCopied ? "Copied" : "Copy"}
</Button>
)}
</Flex>
<Text mb={2} textAlign="center">or scan QR Code:</Text>
<Flex justify="center">
<QRCode
id="payment-method-qr-code"
value={paymentMethodValue}
size={225}
/>
</Flex>
</ModalBody>
</ModalContent>
</Modal>
);
}
Example #13
Source File: index.tsx From calories-in with MIT License | 5 votes |
function Content({ onClose }: Props) {
const [blob, setBlob] = useState<Blob>()
const [url, setUrl] = useState<string>()
const dietForm = useDietForm()
const onUpdate = useCallback((blob: Blob, url: string) => {
setBlob(blob)
setUrl(url)
}, [])
function onViewInBrowser() {
window.open(url, '_blank')
}
return (
<ModalContent>
<ModalHeader fontWeight="normal">
Export{' '}
<Text as="span" fontWeight="bold">
{dietForm.name}
</Text>
</ModalHeader>
<ModalCloseButton />
<ModalBody px={0}>
<Exporter onUpdate={onUpdate} />
</ModalBody>
<ModalFooter>
<VStack spacing={3} width="100%">
{blob && url && (
<DownloadButton
blob={blob}
onClose={onClose}
label="Download"
isFullWidth={true}
fileName={dietForm.name}
isLoading={blob === undefined}
/>
)}
{blob && url && (
<Button
mr={3}
variant="outline"
colorScheme="teal"
onClick={onViewInBrowser}
isFullWidth={true}
>
View in browser
</Button>
)}
<Button isFullWidth={true} variant="solid" onClick={onClose}>
Close
</Button>
</VStack>
</ModalFooter>
</ModalContent>
)
}
Example #14
Source File: Content.tsx From calories-in with MIT License | 5 votes |
function Content({ onClose, title, onImport, action }: Props) {
const { allFoods } = useFoods()
const [blob] = useState(() => {
const allFoodsString = JSON.stringify(allFoods)
return new Blob([allFoodsString])
})
return (
<ModalContent>
<ModalHeader>{title}</ModalHeader>
<ModalCloseButton />
<ModalBody>
<FoodsList
allowsFiltering={false}
height="350px"
itemUsageType="nonInteractive"
/>
</ModalBody>
<ModalFooter>
<HStack spacing={3}>
<Button onClick={onClose}>Close</Button>
{action === 'import' ? (
<Button
isDisabled={allFoods.length === 0}
variant="solid"
colorScheme="teal"
onClick={onImport}
>
{allFoods.length > 0
? `Import ${allFoods.length} ${
allFoods.length === 1 ? 'food' : 'foods'
}`
: 'Import'}
</Button>
) : (
<DownloadButton
blob={blob}
onClose={onClose}
fileName={getUntitledFileName({ prefix: 'foods' })}
label="Export"
isDisabled={allFoods.length === 0}
/>
)}
</HStack>
</ModalFooter>
</ModalContent>
)
}
Example #15
Source File: index.tsx From calories-in with MIT License | 5 votes |
function Form({
ownerName,
notes,
onClose,
initialRef,
onEditNotes,
fieldId,
textAreaHeight,
}: Props) {
const { register, handleSubmit } = useFormContext()
const notesRegister = register('notes')
const notesInputRef = useMergeRefs(notesRegister.ref, initialRef)
const oneTimeCheckActions = useOneTimeCheckActions()
const onSubmit = handleSubmit((form: NotesForm) => {
oneTimeCheckActions.set(`notes-${fieldId}`)
onEditNotes(form.notes || undefined)
onClose()
})
const { errorMessage, isInvalid } = useFormError('name')
return (
<form onSubmit={onSubmit}>
<ModalContent>
<Header ownerName={ownerName} notes={notes} />
<ModalCloseButton />
<ModalBody>
<FormControl isInvalid={isInvalid}>
<FormLabel>Notes</FormLabel>
<Textarea
autoComplete="off"
{...notesRegister}
ref={notesInputRef}
focusBorderColor={isInvalid ? 'red.500' : undefined}
placeholder="Enter notes"
height={textAreaHeight}
/>
<Collapse animateOpacity={true} in={Boolean(errorMessage)}>
<Box minHeight="21px">
<FormErrorMessage>{errorMessage}</FormErrorMessage>
</Box>
</Collapse>
</FormControl>
</ModalBody>
<ModalFooter>
<Button mr={3} onClick={onClose}>
Close
</Button>
<Button
type="submit"
colorScheme="teal"
variant="solid"
onClick={onSubmit}
>
Save
</Button>
</ModalFooter>
</ModalContent>
</form>
)
}
Example #16
Source File: index.tsx From calories-in with MIT License | 5 votes |
function Content({ onClose, initialVariantForm }: Props) {
const dietForm = useDietForm()
const { variantsForms } = dietForm
const getDietFormStatsTree = useGetDietFormStatsTree()
const dietFormStatsTree = getDietFormStatsTree(dietForm)
const initialVariantStatsTree = dietFormStatsTree.subtrees.find(
(statsTree: StatsTree) => statsTree.id === initialVariantForm.fieldId
)
if (!initialVariantStatsTree) {
throw new Error()
}
return (
<ModalContent>
<ModalHeader>Day Details</ModalHeader>
<ModalCloseButton />
<ModalBody>
<VariantsDetailsFormProvider
initialVariantForm={initialVariantForm}
initialVariantStats={initialVariantStatsTree.stats}
>
<form>
<FormFields
initialVariantForm={initialVariantForm}
canEdit={false}
variantsForms={variantsForms}
dietFormStatsTree={dietFormStatsTree}
/>
</form>
</VariantsDetailsFormProvider>
</ModalBody>
<ModalFooter>
<Button onClick={onClose}>Close</Button>
</ModalFooter>
</ModalContent>
)
}
Example #17
Source File: loading-overlay.tsx From video-chat with MIT License | 5 votes |
export function LoadingOverlay(props: Props) {
if (!props.loading) return <></>;
return (
<Modal isOpen={props.loading} isCentered onClose={() => {}}>
<ModalOverlay>
<ModalContent
p="16"
backgroundColor="gray.800"
flexDirection="row"
justifyContent="space-between"
alignItems="center"
>
<Text color="purple.600" fontWeight="bold" fontSize="2rem">Calling</Text>
<motion.div
style={loadingContainer}
variants={loadingContainerVariants}
initial="start"
animate="end"
>
<motion.span
style={loadingCircle}
variants={loadingCircleVariants}
transition={loadingCircleTransition}
/>
<motion.span
style={loadingCircle}
variants={loadingCircleVariants}
transition={loadingCircleTransition}
/>
<motion.span
style={loadingCircle}
variants={loadingCircleVariants}
transition={loadingCircleTransition}
/>
</motion.div>
</ModalContent>
</ModalOverlay>
</Modal>
);
}
Example #18
Source File: ClaimRGTModal.tsx From rari-dApp with GNU Affero General Public License v3.0 | 5 votes |
ClaimRGTModal = ({
isOpen,
onClose,
defaultMode,
}: {
isOpen: boolean;
onClose: () => any;
defaultMode?: ClaimMode;
}) => {
const { t } = useTranslation();
const [amount, setAmount] = useState(0);
const { fuse } = useRari();
// pool2
// private
// yieldagg
const [showPrivate, setShowPrivate] = useState<boolean>(true);
// If user presses meta key or control key + slash they will toggle the private allocation claim mode.
useEffect(() => {
const handler = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.code === "Slash") {
e.preventDefault();
setShowPrivate(true);
}
};
document.addEventListener("keydown", handler);
return () => document.removeEventListener("keydown", handler);
}, []);
return (
<Modal
motionPreset="slideInBottom"
isOpen={isOpen}
onClose={onClose}
isCentered
>
<ModalOverlay />
<ModalContent {...MODAL_PROPS}>
<ModalTitleWithCloseButton
text={t("Claim Rewards")}
onClose={onClose}
/>
<ModalDivider />
<Column
width="100%"
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
p={3}
>
<ClaimRewards showPrivate={showPrivate} />
</Column>
</ModalContent>
</Modal>
);
}
Example #19
Source File: index.tsx From rari-dApp with GNU Affero General Public License v3.0 | 5 votes |
DepositModal = (props: Props) => {
const [mode, setMode] = useState(Mode.DEPOSIT);
const [currentScreen, setCurrentScreen] = useState(CurrentScreen.MAIN);
useEffect(() => {
// When the modal closes return to the main screen.
if (!props.isOpen) {
setCurrentScreen(CurrentScreen.MAIN);
}
}, [props.isOpen]);
const poolType = usePoolType();
const [selectedToken, setSelectedToken] = useState(() => {
if (poolType === Pool.ETH) {
return "ETH";
} else {
return "USDC";
}
});
return (
<Modal
motionPreset="slideInBottom"
isOpen={props.isOpen}
onClose={props.onClose}
isCentered
>
<ModalOverlay />
<ModalContent
{...MODAL_PROPS}
height={{
md: poolHasDivergenceRisk(poolType) ? "320px" : "295px",
base: poolHasDivergenceRisk(poolType) ? "350px" : "310px",
}}
>
{currentScreen === CurrentScreen.MAIN ? (
<AmountSelect
onClose={props.onClose}
openCoinSelect={() => setCurrentScreen(CurrentScreen.COIN_SELECT)}
openOptions={() => setCurrentScreen(CurrentScreen.OPTIONS)}
selectedToken={selectedToken}
mode={mode}
/>
) : currentScreen === CurrentScreen.COIN_SELECT ? (
<TokenSelect
onClose={() => setCurrentScreen(CurrentScreen.MAIN)}
onSelectToken={setSelectedToken}
mode={mode}
/>
) : (
<OptionsMenu
onClose={() => setCurrentScreen(CurrentScreen.MAIN)}
onSetMode={setMode}
mode={mode}
/>
)}
</ModalContent>
</Modal>
);
}
Example #20
Source File: About.tsx From calories-in with MIT License | 4 votes |
function About({ isOpen, onClose }: Props) {
function onContact() {
window.location.href = 'mailto:[email protected]'
}
return (
<Modal isOpen={isOpen} onClose={onClose} size="2xl" scrollBehavior="inside">
<ModalOverlay />
<ModalContent>
<ModalHeader>About </ModalHeader>
<ModalCloseButton />
<ModalBody>
<Text fontSize="lg">
<Text>Hi, I'm Vladimir, the person behind this project.</Text>
<br />
<Text>
<Text fontWeight="semibold" as="span" textColor="teal.600">
Calories-In
</Text>{' '}
is made for people who follow meal plans that involve preparing
everything by yourself and gives them full control to fine tune
the nutritional values.
</Text>
<br />
<Text>
The idea was born out of my experience of trying to find a better
alternative to Google Sheets for calculating the macros of my own
meal plans. I wanted to be able to do this on desktop as it's more
convenient but nothing really felt fast and simple enough.
</Text>
<br />
<Text>The main differences to other apps in this space are:</Text>
<br />
<List ml={8}>
<ListItem>
<ListIcon as={CheckCircle} color="teal.600" />
<Text fontWeight="semibold" as="span" textColor="teal.600">
Faster search
</Text>{' '}
: There are actually not that many foods you need when you
prepare everything yourself. This means all of the food data can
be downloaded beforehand which makes the search super fast. Of
course you can add your own foods if you'd like.{' '}
</ListItem>
<br />
<ListItem>
<ListIcon as={CheckCircle} color="teal.600" />
<Text fontWeight="semibold" as="span" textColor="teal.600">
Undo/Redo
</Text>{' '}
: Building a plan from scratch or updating an existing one
involves some back and forth choosing the right foods and
adjusting their amounts. This is especially true if you want to
be as close as possible to a specific calorie limit and have
your macros be a certain percentages split.
</ListItem>
<br />
<ListItem>
<ListIcon as={CheckCircle} color="teal.600" />
<Text fontWeight="semibold" as="span" textColor="teal.600">
Faster export
</Text>{' '}
: Creating the PDF file for your meal plan is done entirely
inside the browser. It does not involve generating and
downloading it from a server. This means I can keep the cost of
running the website low and you get your file in just a few
seconds.
</ListItem>
<br />
<ListItem>
<ListIcon as={CheckCircle} color="teal.600" />
<Text fontWeight="semibold" as="span" textColor="teal.600">
Simpler
</Text>{' '}
: There are no other pages except the editor. Most of the other
tools are bloated with additional features for professionals,
such as managing clients, creating invoices, etc.
</ListItem>
<br />
<ListItem>
<ListIcon as={CheckCircle} color="teal.600" />
<Text fontWeight="semibold" as="span" textColor="teal.600">
Fully mobile
</Text>{' '}
: You can use your phone or tablet to build your meal plans
right from your browser. If you add the app to your home screen
it will look and feel almost like a native one.
</ListItem>
</List>
<Text>
<br />
Let me know if you found it useful or have any comments in
general:
</Text>
<br />
<Button size="lg" colorScheme="teal" onClick={onContact}>
Contact me directly
</Button>
<br />
<br />
<Text>No email will go unanswered, I promise :)</Text>
</Text>
</ModalBody>
<ModalFooter>
<Button size="lg" onClick={onClose}>
Close
</Button>
</ModalFooter>
</ModalContent>
</Modal>
)
}
Example #21
Source File: carousel.tsx From notebook with MIT License | 4 votes |
Carousel: React.SFC<CarouselProps> = ({
onOpen,
onClose,
isOpen,
repoId
}) => {
const [[page, direction], setPage] = React.useState([0, 0]);
const [imageIndex, setImageIndex] = React.useState<number>(0);
const paginate = (newDirection: number) => {
setPage([page + newDirection, newDirection]);
};
React.useEffect(() => {
setImageIndex(repoId);
}, [repoId]);
const nextImage = (newDirection: number) => {
paginate(newDirection);
setImageIndex(imageIndex + 1 < coverImages.length ? imageIndex + 1 : 0);
};
const prevImage = (newDirection: number) => {
paginate(newDirection);
setImageIndex(
0 === imageIndex ? coverImages.length - 1 : imageIndex - 1
);
};
return (
<Modal isCentered onClose={onClose} size={"6xl"} isOpen={isOpen}>
<ModalOverlay />
<ModalContent>
<ModalBody padding="0">
<div className="carousel-container">
<AnimatePresence initial={false} custom={direction}>
<motion.img
key={page}
src={coverImages[imageIndex]}
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
transition={{
x: { type: "spring", stiffness: 300, damping: 30 },
opacity: { duration: 0.2 }
}}
drag="x"
dragConstraints={{ left: 0, right: 0 }}
dragElastic={1}
onDragEnd={(e, { offset, velocity }) => {
const swipe = swipePower(offset.x, velocity.x);
if (swipe < -swipeConfidenceThreshold) {
paginate(1);
} else if (swipe > swipeConfidenceThreshold) {
paginate(-1);
}
}}
/>
</AnimatePresence>
<div className="next" onClick={() => nextImage(1)}>
<IconButton
aria-label="left image"
icon={<ChevronLeftIcon />}
cursor="pointer"
as={ChevronRightIcon}
size="md"
colorScheme="teal"
borderRadius="full"
/>
</div>
<div className="prev" onClick={() => prevImage(-1)}>
<IconButton
aria-label="right image"
icon={<ChevronRightIcon />}
cursor="pointer"
as={ChevronLeftIcon}
size="md"
colorScheme="teal"
borderRadius="full"
/>
</div>
</div>
</ModalBody>
</ModalContent>
</Modal>
);
}
Example #22
Source File: note-form.tsx From notebook with MIT License | 4 votes |
NoteForm: React.SFC<NoteFormProps> = ({
isOpen,
onClose,
selectedNote,
handleNoteCreate,
handleNoteUpdate
}) => {
const { register, handleSubmit, formState, errors } = useForm<FormInputs>({
mode: "onChange"
});
const onSubmit: SubmitHandler<FormInputs> = data => {
let newNote: note = {
id: "",
title: data.title,
body: data.body
};
if (handleNoteCreate) {
newNote.id = nanoid();
if (handleNoteCreate) handleNoteCreate(newNote);
} else {
newNote.id = selectedNote ? selectedNote.id : "";
if (handleNoteUpdate) handleNoteUpdate(newNote);
}
onClose();
};
const validateTitle = (value: string) => {
if (!value) {
return "Title is required";
} else return true;
};
const validateBody = (value: string) => {
if (!value) {
return "Body is required";
} else return true;
};
return (
<Modal
isOpen={isOpen}
onClose={onClose}
size="lg"
isCentered
motionPreset="slideInBottom"
>
<ModalOverlay />
<ModalContent>
<form onSubmit={handleSubmit(onSubmit)}>
<ModalHeader>{selectedNote ? "Edit" : "Create"} a Note</ModalHeader>
<ModalCloseButton />
<ModalBody pb={6}>
<FormControl isInvalid={!!errors?.title} isRequired>
<FormLabel>Title</FormLabel>
<Input
name="title"
placeholder="Title"
defaultValue={selectedNote?.title}
ref={register({ validate: validateTitle })}
/>
<FormErrorMessage>
{!!errors?.title && errors?.title?.message}
</FormErrorMessage>
</FormControl>
<FormControl size="lg" mt={4} isInvalid={!!errors?.body} isRequired>
<FormLabel>Body</FormLabel>
<Textarea
name="body"
placeholder="Body"
size="md"
borderRadius="5px"
defaultValue={selectedNote?.body}
ref={register({ validate: validateBody })}
/>
<FormErrorMessage>
{!!errors?.body && errors?.body?.message}
</FormErrorMessage>
</FormControl>
</ModalBody>
<ModalFooter>
<Button
type="submit"
colorScheme="blue"
isLoading={formState.isSubmitting}
mr={3}
>
Save
</Button>
<Button onClick={onClose}>Cancel</Button>
</ModalFooter>
</form>
</ModalContent>
</Modal>
);
}
Example #23
Source File: offline-data-card.tsx From portfolio with MIT License | 4 votes |
RepositoryCard = (props: RepositoryCardProps) => {
const {
key,
title,
description,
cover,
blurHash,
technologies,
url,
live,
stars,
fork,
} = props;
const { isOpen, onOpen, onClose } = useDisclosure();
const handleClick = () => {
onOpen();
// window.open(link);
// if (type == "link" || type == "article") {
// window.open(link);
// } else {
// onOpen();
// }
};
const handleLinkClick = (
e: React.MouseEvent<HTMLParagraphElement, MouseEvent>,
link: string
) => {
window.open(link);
e.stopPropagation();
};
const transition = { duration: 0.5, ease: [0.43, 0.13, 0.23, 0.96] };
const thumbnailVariants = {
initial: { scale: 0.9, opacity: 0 },
enter: { scale: 1, opacity: 1, transition },
exit: {
scale: 0.5,
opacity: 0,
transition: { duration: 1.5, ...transition }
}
};
const imageVariants = {
hover: { scale: 1.1 }
};
return (
<CardTransition>
<Box onClick={handleClick} cursor="pointer" size="xl">
<VStack
// w="100%"
rounded="xl"
borderWidth="1px"
bg={useColorModeValue("white", "gray.800")}
borderColor={useColorModeValue("gray.100", "gray.700")}
_hover={{
shadow: "lg",
textDecoration: "none"
}}
overflow="hidden"
align="start"
spacing={0}
>
<Box position="relative" w="100%">
<MotionBox variants={thumbnailVariants}>
<MotionBox
whileHover="hover"
variants={imageVariants}
transition={transition}
>
<AspectRatio
ratio={1.85 / 1}
maxW="400px"
w="100%"
borderBottomWidth="1px"
borderColor={useColorModeValue("gray.100", "gray.700")}
>
{/* <Image
src={cover}
fallback={<Skeleton />}
objectFit="cover"
/> */}
<LazyImage
src={cover}
blurHash={blurHash}
/>
</AspectRatio>
</MotionBox>
</MotionBox>
</Box>
<VStack py={2} px={[2, 4]} spacing={1} align="start" w="100%">
<Flex justifyContent={"space-between"} width="100%">
<Tooltip hasArrow label="Github link" placement="top">
<HStack>
<Icon as={FiGithub} boxSize="0.9em" mt={"1px"} />
{/* <Link href={url} isExternal> */}
<Text
fontSize="sm"
noOfLines={1}
fontWeight="600"
align="left"
onClick={e => handleLinkClick(e, url)}
>
{title}
</Text>
</HStack>
</Tooltip>
{/* </Link> */}
<Flex>
<Icon as={AiOutlineStar} boxSize="0.9em" mt={"1px"} />
<Box as="span" ml="1" fontSize="sm">
{stars}
</Box>
</Flex>
</Flex>
<Flex justifyContent={"space-between"} width="100%">
<Box>
<HStack spacing="1">
{technologies.map(tech => (
<Tag size="sm" colorScheme={getTagColor(tech)}>
<Text fontSize={["0.55rem", "inherit", "inherit"]}>
{tech}
</Text>
</Tag>
))}
</HStack>
</Box>
</Flex>
{/* <Flex justifyContent={"space-between"} width="100%">
<Flex>
<AiOutlineStar color="teal.300" />
<Box as="span" ml="1" fontSize="sm">
{stars}
</Box>
</Flex>
<Box >
<Text
fontSize="xs"
fontWeight="400"
color={useColorModeValue("gray.400", "gray.500")}
>
{created}
</Text>
</Box>
</Flex> */}
</VStack>
</VStack>
<Modal isOpen={isOpen} onClose={onClose} isCentered allowPinchZoom>
<ModalOverlay />
<ModalContent bg="none" maxW={"28rem"} w="auto">
<ModalBody p={0} rounded="lg" overflow="hidden" bg="none">
<Center>
<Image src={cover} rounded="lg" />
{/* {type == "image" ? (
<Image src={cover} rounded="lg" />
) : (
<ReactPlayer url={link} controls playing />
)} */}
</Center>
</ModalBody>
</ModalContent>
</Modal>
</Box>
</CardTransition>
);
}
Example #24
Source File: index.tsx From jsonschema-editor-react with Apache License 2.0 | 4 votes |
SchemaArray: React.FunctionComponent<SchemaArrayProps> = (
props: React.PropsWithChildren<SchemaArrayProps>
) => {
const { schemaState, isReadOnly } = props;
const state = useState(schemaState.items as JSONSchema7);
const isReadOnlyState = useState(isReadOnly);
const { length } = state.path.filter((name) => name !== "properties");
const tagPaddingLeftStyle = {
paddingLeft: `${20 * (length + 1)}px`,
};
const onCloseAdvanced = (): void => {
localState.isAdvancedOpen.set(false);
};
const showadvanced = (): void => {
localState.isAdvancedOpen.set(true);
};
const focusRef = React.createRef<HTMLElement>();
const localState = useState({
isAdvancedOpen: false,
});
return (
<>
<Flex
direction="row"
wrap="nowrap"
className="array-item"
mt={2}
mr={5}
style={tagPaddingLeftStyle}
>
<Input
key="Items"
isDisabled
value="Items"
size="sm"
flexShrink={1}
margin={2}
variant="outline"
/>
<Checkbox isDisabled margin={2} colorScheme="blue" />
<Select
variant="outline"
isDisabled={isReadOnlyState.value}
value={state.type.value as JSONSchema7TypeName}
size="sm"
margin={2}
placeholder="Choose data type"
onChange={(evt: React.ChangeEvent<HTMLSelectElement>) => {
const newSchema = handleTypeChange(
evt.target.value as JSONSchema7TypeName,
false
);
state.set(newSchema as JSONSchema7);
}}
>
{SchemaTypes.map((item, index) => {
return (
<option key={String(index)} value={item}>
{item}
</option>
);
})}
</Select>
<Input
value={state.title.value}
isDisabled={isReadOnlyState.value}
size="sm"
margin={2}
variant="outline"
placeholder="Add Title"
onChange={(evt: React.ChangeEvent<HTMLInputElement>) => {
state.title.set(evt.target.value);
}}
/>
<Input
value={state.description.value}
isDisabled={isReadOnlyState.value}
size="sm"
margin={2}
variant="outline"
placeholder="Add Description"
onChange={(evt: React.ChangeEvent<HTMLInputElement>) => {
state.description.set(evt.target.value);
}}
/>
<Tooltip
hasArrow
aria-label="Advanced Settings"
label="Advanced Settings"
placement="top"
>
<IconButton
isRound
isDisabled={isReadOnlyState.value}
size="sm"
mt={2}
mb={2}
ml={1}
variant="link"
colorScheme="blue"
fontSize="16px"
icon={<FiSettings />}
aria-label="Advanced Settings"
onClick={() => {
showadvanced();
}}
/>
</Tooltip>
{state.type.value === "object" && (
<Tooltip
hasArrow
aria-label="Add Child Node"
label="Add Child Node"
placement="top"
>
<IconButton
isRound
isDisabled={isReadOnlyState.value}
size="sm"
mt={2}
mb={2}
mr={2}
variant="link"
colorScheme="green"
fontSize="16px"
icon={<IoIosAddCircleOutline />}
aria-label="Add Child Node"
onClick={() => {
const fieldName = `field_${random()}`;
(state.properties as State<{
[key: string]: JSONSchema7;
}>)[fieldName].set(getDefaultSchema(DataType.string));
}}
/>
</Tooltip>
)}
</Flex>
{state.type?.value === "object" && (
<SchemaObject isReadOnly={isReadOnlyState} schemaState={state} />
)}
{state.type?.value === "array" && (
<SchemaArray isReadOnly={isReadOnlyState} schemaState={state} />
)}
<Modal
isOpen={localState.isAdvancedOpen.get()}
finalFocusRef={focusRef}
size="lg"
onClose={onCloseAdvanced}
>
<ModalOverlay />
<ModalContent>
<ModalHeader textAlign="center">Advanced Schema Settings</ModalHeader>
<ModalBody>
<AdvancedSettings itemStateProp={state} />
</ModalBody>
<ModalFooter>
<Button
colorScheme="blue"
variant="ghost"
mr={3}
onClick={onCloseAdvanced}
>
Close
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
);
}
Example #25
Source File: index.tsx From jsonschema-editor-react with Apache License 2.0 | 4 votes |
SchemaObject: React.FunctionComponent<SchemaObjectProps> = (
props: React.PropsWithChildren<SchemaObjectProps>
) => {
const { schemaState, isReadOnly } = props;
const schema = useState(schemaState);
const properties = useState(schema.properties);
const propertiesOrNull:
| State<{
[key: string]: JSONSchema7Definition;
}>
| undefined = properties.ornull;
const isReadOnlyState = useState(isReadOnly);
const onCloseAdvanced = (): void => {
localState.isAdvancedOpen.set(false);
};
const showadvanced = (item: string): void => {
localState.isAdvancedOpen.set(true);
localState.item.set(item);
};
const focusRef = React.createRef<HTMLElement>();
const localState = useState({
isAdvancedOpen: false,
item: "",
});
if (!propertiesOrNull) {
return <></>;
} else {
return (
<div className="object-style">
{propertiesOrNull?.keys?.map((name) => {
return (
<SchemaItem
key={String(name)}
itemStateProp={
propertiesOrNull.nested(name as string) as State<JSONSchema7>
}
parentStateProp={schema}
name={name as string}
showadvanced={showadvanced}
required={schema.required.value as string[]}
isReadOnly={isReadOnlyState}
/>
);
})}
<Modal
isOpen={localState.isAdvancedOpen.get()}
finalFocusRef={focusRef}
size="lg"
onClose={onCloseAdvanced}
>
<ModalOverlay />
<ModalContent>
<ModalHeader textAlign="center">
Advanced Schema Settings
</ModalHeader>
<ModalBody>
<AdvancedSettings
itemStateProp={
propertiesOrNull.nested(
localState.item.value as string
) as State<JSONSchema7>
}
/>
</ModalBody>
<ModalFooter>
<Button
colorScheme="blue"
variant="ghost"
mr={3}
onClick={onCloseAdvanced}
>
Close
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</div>
);
}
}
Example #26
Source File: AddAssetModal.tsx From rari-dApp with GNU Affero General Public License v3.0 | 4 votes |
AddAssetModal = ({
comptrollerAddress,
poolName,
poolID,
isOpen,
onClose,
existingAssets,
}: {
comptrollerAddress: string;
poolName: string;
poolID: string;
isOpen: boolean;
onClose: () => any;
existingAssets: USDPricedFuseAsset[];
}) => {
const { t } = useTranslation();
const [tokenAddress, _setTokenAddress] = useState<string>("");
const tokenData = useTokenData(tokenAddress);
const isEmpty = tokenAddress.trim() === "";
return (
<Modal
motionPreset="slideInBottom"
isOpen={isOpen}
onClose={onClose}
isCentered
>
<ModalOverlay />
<ModalContent {...MODAL_PROPS}>
<Heading fontSize="27px" my={4} textAlign="center">
{t("Add Asset")}
</Heading>
<ModalDivider />
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="center"
pb={4}
>
{!isEmpty ? (
<>
{tokenData?.logoURL ? (
<Image
mt={4}
src={tokenData.logoURL}
boxSize="50px"
borderRadius="50%"
backgroundImage={`url(${SmallWhiteCircle})`}
backgroundSize="100% auto"
/>
) : null}
<Heading
my={tokenData?.symbol ? 3 : 6}
fontSize="22px"
color={tokenData?.color ?? "#FFF"}
>
{tokenData
? tokenData.name ?? "Invalid Address!"
: "Loading..."}
</Heading>
</>
) : null}
<Center px={4} mt={isEmpty ? 4 : 0} width="100%">
<Input
width="100%"
textAlign="center"
placeholder={t(
"Token Address: 0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
)}
height="40px"
variant="filled"
size="sm"
value={tokenAddress}
onChange={(event) => {
const address = event.target.value;
_setTokenAddress(address);
}}
{...DASHBOARD_BOX_PROPS}
_placeholder={{ color: "#e0e0e0" }}
_focus={{ bg: "#121212" }}
_hover={{ bg: "#282727" }}
bg="#282727"
/>
{!existingAssets.some(
// If ETH hasn't been added:
(asset) => asset.underlyingToken === ETH_TOKEN_DATA.address
) ? (
<DashboardBox
flexShrink={0}
as="button"
ml={2}
height="40px"
borderRadius="10px"
px={2}
fontSize="sm"
fontWeight="bold"
onClick={() => _setTokenAddress(ETH_TOKEN_DATA.address)}
>
<Center expand>ETH</Center>
</DashboardBox>
) : null}
</Center>
{tokenData?.symbol ? (
<>
<ModalDivider mt={4} />
<AssetSettings
comptrollerAddress={comptrollerAddress}
tokenData={tokenData}
closeModal={onClose}
poolName={poolName}
poolID={poolID}
existingAssets={existingAssets}
/>
</>
) : null}
</Column>
</ModalContent>
</Modal>
);
}
Example #27
Source File: index.tsx From calories-in with MIT License | 4 votes |
function Form({
onClose,
nameInputRef,
title,
food,
canEdit,
onFoodCreatedOrUpdated,
isEditing,
onToggleEdit,
onDelete,
}: Props) {
const { onSubmit } = useSubmitFoodForm({
onComplete: (newOrUpdatedFood: Food) => {
onFoodCreatedOrUpdated && onFoodCreatedOrUpdated(newOrUpdatedFood, food)
onClose()
},
})
const { tabNames, onTabNameChange, selectedTabName } = useTabs({
isEditing,
food,
})
return (
<form onSubmit={onSubmit}>
<ModalContent>
<Header
title={title}
canEdit={canEdit}
isEditing={isEditing}
onClose={onClose}
onToggleEdit={onToggleEdit}
/>
<ModalCloseButton />
<ModalBody>
<VStack spacing={6} align="stretch\">
<VStack spacing={2} align="stretch">
{isEditing ? (
<StatFormField
textInputRef={nameInputRef}
name="name"
label="Name"
inputType="text"
isRequired={true}
isReadOnly={!isEditing}
hasDivider={false}
/>
) : (
<Text fontSize="xl" fontWeight="bold">
{food?.name}
</Text>
)}
<StatFormField
name="categoryId"
label="Category"
inputType="foodCategory"
isRequired={true}
isReadOnly={!isEditing}
/>
</VStack>
<Tabs
nameInputRef={nameInputRef}
isEditing={isEditing}
food={food}
tabNames={tabNames}
onTabNameChange={onTabNameChange}
selectedTabName={selectedTabName}
/>
</VStack>
{isEditing && food && (
<Box>
<Divider />
<Button width="100%" my={6} colorScheme="red" onClick={onDelete}>
Delete food
</Button>
</Box>
)}
</ModalBody>
<Footer onClose={onClose} onSubmit={onSubmit} isEditing={isEditing} />
</ModalContent>
</form>
)
}
Example #28
Source File: AddRewardsDistributorModal.tsx From rari-dApp with GNU Affero General Public License v3.0 | 4 votes |
AddRewardsDistributorModal = ({
comptrollerAddress,
poolName,
poolID,
isOpen,
onClose,
}: {
comptrollerAddress: string;
poolName: string;
poolID: string;
isOpen: boolean;
onClose: () => any;
}) => {
const { fuse, address: userAddress } = useRari();
const { t } = useTranslation();
const toast = useToast();
const [isDeploying, setIsDeploying] = useState(false);
const [address, setAddress] = useState<string>(
""
);
const [rewardToken, setRewardToken] = useState<string>("");
// If you have selected "Add RewardsDistributor, this value will be filled"
const [nav, setNav] = useState<Nav>(Nav.CREATE);
// Stepper
const [activeStep, setActiveStep] = useState<0 | 1 | 2>(0);
const tokenData = useTokenData(rewardToken);
const isEmpty = address.trim() === "";
useEffect(() => {
const isRewardsDistributorAddress = nav === Nav.ADD;
if (isRewardsDistributorAddress) {
setRewardToken("");
}
try {
const validAddress = Web3.utils.toChecksumAddress(address);
if (validAddress && isRewardsDistributorAddress) {
const rd = createRewardsDistributor(address, fuse);
rd.methods
.rewardToken()
.call()
.then((tokenAddr: string) => setRewardToken(tokenAddr));
}
// If we're creating a rewardsDistributor then this is the rewardToken
if (validAddress && !isRewardsDistributorAddress) {
setRewardToken(address);
}
} catch (err) {
return;
}
// If we're adding a rewardsDistributor then get the rewardToken
}, [fuse, address, nav]);
const handleDeploy = async () => {
if (!tokenData) return;
setIsDeploying(true);
let rDAddress = address;
try {
if (nav === Nav.CREATE) {
rDAddress = await deploy();
}
} catch (err) {
console.log({ err });
setIsDeploying(false);
toast({
title: "Error deploying RewardsDistributor",
description: "",
status: "error",
duration: 10000,
isClosable: true,
position: "top-right",
});
return;
}
setActiveStep(1);
try {
await addRDToComptroller(comptrollerAddress, rDAddress, fuse);
setIsDeploying(false);
onClose();
} catch (err) {
console.log({ err });
setIsDeploying(false);
toast({
title: "Error adding RewardsDistributor to Comptroller",
description: "",
status: "error",
duration: 10000,
isClosable: true,
position: "top-right",
});
return;
}
};
// Deploy new RD
const deploy = async (): Promise<string> => {
if (!tokenData) throw new Error("No tokendata ");
const deployedDistributor = await fuse.deployRewardsDistributor(
tokenData.address,
{
from: userAddress,
}
);
toast({
title: "RewardsDistributor Deployed",
description: "RewardsDistributor for " + tokenData.symbol + " deployed",
status: "success",
duration: 2000,
isClosable: true,
position: "top-right",
});
const rDAddress = deployedDistributor.options.address;
return rDAddress;
};
const addRDToComptroller = async (
comptrollerAddress: string,
rDAddress: string,
fuse: Fuse
) => {
const comptroller = await createComptroller(comptrollerAddress, fuse);
if (!comptroller || !comptroller.methods._addRewardsDistributor) {
throw new Error("Could not create Comptroller");
}
// Add distributor to pool Comptroller
await comptroller.methods
._addRewardsDistributor(rDAddress)
.send({ from: userAddress });
toast({
title: "RewardsDistributor Added to Pool",
description: "",
status: "success",
duration: 2000,
isClosable: true,
position: "top-right",
});
};
const subtitle = useMemo(() => {
if (nav === Nav.CREATE) {
return tokenData
? tokenData.name ?? "Invalid ERC20 Token Address!"
: "Loading...";
} else {
return tokenData
? tokenData.name ?? "Invalid RewardsDistributor Address!"
: "Loading...";
}
}, [tokenData, nav]);
return (
<Modal
motionPreset="slideInBottom"
isOpen={isOpen}
onClose={onClose}
isCentered
size="lg"
>
<ModalOverlay />
<ModalContent {...MODAL_PROPS}>
<Heading fontSize="27px" my={4} textAlign="center">
{nav === Nav.CREATE
? t("Deploy Rewards Distributor")
: t("Add Rewards Distributor")}
</Heading>
<ModalDivider />
<Box h="100%" w="100%" bg="">
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
bg=""
p={4}
>
<RadioGroup onChange={(value: Nav) => setNav(value)} value={nav}>
<Stack direction="row">
<Radio value={Nav.CREATE} disabled={isDeploying}>
Create
</Radio>
<Radio value={Nav.ADD} disabled={isDeploying}>
Add
</Radio>
</Stack>
</RadioGroup>
</Row>
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="center"
pb={4}
>
{!isEmpty ? (
<>
{tokenData?.logoURL ? (
<Image
mt={4}
src={tokenData.logoURL}
boxSize="50px"
borderRadius="50%"
backgroundImage={`url(${SmallWhiteCircle})`}
backgroundSize="100% auto"
/>
) : null}
<Heading
my={tokenData?.symbol ? 3 : 6}
fontSize="22px"
color={tokenData?.color ?? "#FFF"}
>
{subtitle}
</Heading>
</>
) : null}
<Center px={4} mt={isEmpty ? 4 : 0} width="100%">
<Input
width="100%"
textAlign="center"
placeholder={
nav === Nav.CREATE
? t(
"Token Address: 0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
)
: t("RewardsDistributor Address:")
}
height="40px"
variant="filled"
size="sm"
value={address}
onChange={(event) => setAddress(event.target.value)}
{...DASHBOARD_BOX_PROPS}
_placeholder={{ color: "#e0e0e0" }}
_focus={{ bg: "#121212" }}
_hover={{ bg: "#282727" }}
bg="#282727"
/>
</Center>
{isDeploying && (
<Box my={3} w="100%" h="100%">
<TransactionStepper
activeStep={activeStep}
tokenData={tokenData}
steps={steps}
/>
</Box>
)}
{tokenData?.symbol && (
<Box px={4} mt={4} width="100%">
<Button
fontWeight="bold"
fontSize="2xl"
borderRadius="10px"
width="100%"
height="70px"
color={tokenData.overlayTextColor! ?? "#000"}
bg={tokenData.color! ?? "#FFF"}
_hover={{ transform: "scale(1.02)" }}
_active={{ transform: "scale(0.95)" }}
// isLoading={isDeploying}
disabled={isDeploying}
onClick={handleDeploy}
>
{isDeploying
? steps[activeStep]
: nav === Nav.CREATE
? t("Deploy RewardsDistributor")
: t("Add RewardsDistributor")}
</Button>
</Box>
)}
</Column>
</Box>
</ModalContent>
</Modal>
);
}
Example #29
Source File: EditRewardsDistributorModal.tsx From rari-dApp with GNU Affero General Public License v3.0 | 4 votes |
EditRewardsDistributorModal = ({
rewardsDistributor,
pool,
isOpen,
onClose,
}: {
rewardsDistributor: RewardsDistributor;
pool: FusePoolData;
isOpen: boolean;
onClose: () => any;
}) => {
const { t } = useTranslation();
const { address, fuse } = useRari();
const rewardsDistributorInstance = useRewardsDistributorInstance(
rewardsDistributor.address
);
const tokenData = useTokenData(rewardsDistributor.rewardToken);
const isAdmin = address === rewardsDistributor.admin;
// Balances
const { data: balanceERC20 } = useTokenBalance(
rewardsDistributor.rewardToken,
rewardsDistributor.address
);
const { data: myBalance } = useTokenBalance(rewardsDistributor.rewardToken);
const toast = useToast();
// Inputs
const [sendAmt, setSendAmt] = useState<number>(0);
const [supplySpeed, setSupplySpeed] = useState<number>(0.001);
const [borrowSpeed, setBorrowSpeed] = useState<number>(0.001);
// Loading states
const [fundingDistributor, setFundingDistributor] = useState(false);
const [seizing, setSeizing] = useState(false);
const [changingSpeed, setChangingSpeed] = useState(false);
const [changingBorrowSpeed, setChangingBorrowSpeed] = useState(false);
const [selectedAsset, setSelectedAsset] = useState<
USDPricedFuseAsset | undefined
>(pool?.assets[0] ?? undefined);
// RewardsSpeeds
const [supplySpeedForCToken, borrowSpeedForCToken] = useRewardSpeedsOfCToken(
rewardsDistributor.address,
selectedAsset?.cToken
);
const { hasCopied, onCopy } = useClipboard(rewardsDistributor?.address ?? "");
// Sends tokens to distributor
const fundDistributor = async () => {
// Create ERC20 instance of rewardToken
const token = new fuse.web3.eth.Contract(
JSON.parse(
fuse.compoundContracts["contracts/EIP20Interface.sol:EIP20Interface"]
.abi
),
rewardsDistributor.rewardToken
);
setFundingDistributor(true);
try {
await token.methods
.transfer(
rewardsDistributor.address,
Fuse.Web3.utils
.toBN(sendAmt)
.mul(
Fuse.Web3.utils
.toBN(10)
.pow(Fuse.Web3.utils.toBN(tokenData?.decimals ?? 18))
)
)
.send({
from: address,
});
setFundingDistributor(false);
} catch (err) {
handleGenericError(err, toast);
setFundingDistributor(false);
}
};
// Adds LM to supply side of a CToken in this fuse pool
const changeSupplySpeed = async () => {
try {
if (!isAdmin) throw new Error("User is not admin of this Distributor!");
setChangingSpeed(true);
await rewardsDistributorInstance.methods
._setCompSupplySpeed(
selectedAsset?.cToken,
Fuse.Web3.utils.toBN(supplySpeed * 10 ** (tokenData?.decimals ?? 18)) // set supplySpeed to 0.001e18 for now
)
.send({ from: address });
setChangingSpeed(false);
} catch (err) {
handleGenericError(err, toast);
setChangingSpeed(false);
}
};
// Adds LM to supply side of a CToken in this fuse pool
const changeBorrowSpeed = async () => {
try {
if (!isAdmin) throw new Error("User is not admin of this Distributor!");
setChangingBorrowSpeed(true);
await rewardsDistributorInstance.methods
._setCompBorrowSpeed(
selectedAsset?.cToken,
Fuse.Web3.utils.toBN(borrowSpeed * 10 ** (tokenData?.decimals ?? 18)) // set supplySpeed to 0.001e18 for now
)
.send({ from: address });
setChangingBorrowSpeed(false);
} catch (err) {
handleGenericError(err, toast);
setChangingBorrowSpeed(false);
}
};
const handleSeizeTokens = async () => {
setSeizing(true);
if (isAdmin) {
await rewardsDistributorInstance.methods._grantComp(
address,
balanceERC20
);
} else {
toast({
title: "Admin Only!",
description: "Only admin can seize tokens!",
status: "error",
duration: 9000,
isClosable: true,
position: "top-right",
});
}
setSeizing(false);
};
return (
<Modal
motionPreset="slideInBottom"
isOpen={isOpen}
onClose={onClose}
isCentered
>
<ModalOverlay />
<ModalContent {...MODAL_PROPS}>
<Heading fontSize="27px" my={4} textAlign="center">
{t("Edit Rewards Distributor")}
</Heading>
<ModalDivider />
{/* RewardToken data */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="center"
p={4}
>
<>
{tokenData?.logoURL ? (
<Image
mt={4}
src={tokenData.logoURL}
boxSize="50px"
borderRadius="50%"
backgroundImage={`url(${SmallWhiteCircle})`}
backgroundSize="100% auto"
/>
) : null}
<Heading
my={tokenData?.symbol ? 3 : 6}
fontSize="22px"
color={tokenData?.color ?? "#FFF"}
>
{tokenData ? tokenData.name ?? "Invalid Address!" : "Loading..."}
</Heading>
<Text>
{balanceERC20 && tokenData && tokenData.decimals
? (
parseFloat(balanceERC20?.toString()) /
10 ** tokenData.decimals
).toFixed(3)
: 0}{" "}
{tokenData?.symbol}
</Text>
<Text onClick={onCopy}>
Contract: {shortAddress(rewardsDistributor.address)}{" "}
{hasCopied && "Copied!"}
</Text>
</>
</Column>
<AdminAlert
isAdmin={isAdmin}
mt={2}
isNotAdminText="You are not the admin of this RewardsDistributor. Only the admin can configure rewards."
/>
{/* Basic Info */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
py={4}
>
{/* <Row mainAxisAlignment="flex-start" crossAxisAlignment="center">
<Text>Address: {rewardsDistributor.address}</Text>
</Row>
<Row mainAxisAlignment="flex-start" crossAxisAlignment="center">
<Text>Admin: {rewardsDistributor.admin}</Text>
</Row>
<Row mainAxisAlignment="flex-start" crossAxisAlignment="center">
<Text>
Balance:{" "}
{balanceERC20 ? parseFloat(balanceERC20?.toString()) / 1e18 : 0}{" "}
{tokenData?.symbol}
</Text>
</Row> */}
<ModalDivider />
{/* Fund distributor */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
p={4}
>
<Heading fontSize={"lg"}> Fund Distributor </Heading>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="center"
mt={1}
>
<NumberInput
step={0.1}
min={0}
onChange={(valueString) => {
console.log({ valueString });
setSendAmt(parseFloat(valueString));
}}
>
<NumberInputField
width="100%"
textAlign="center"
placeholder={"0 " + tokenData?.symbol}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Button
onClick={fundDistributor}
bg="black"
disabled={fundingDistributor}
>
{fundingDistributor ? <Spinner /> : "Send"}
</Button>
{isAdmin && (!balanceERC20?.isZero() ?? false) && (
<Button onClick={handleSeizeTokens} bg="red" disabled={seizing}>
{seizing ? <Spinner /> : "Withdraw Tokens"}
</Button>
)}
</Row>
<Text mt={1}>
Your balance:{" "}
{myBalance
? (
parseFloat(myBalance?.toString()) /
10 ** (tokenData?.decimals ?? 18)
).toFixed(2)
: 0}{" "}
{tokenData?.symbol}
</Text>
</Column>
{/* Add or Edit a CToken to the Distributor */}
{pool.assets.length ? (
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
p={4}
>
<Heading fontSize={"lg"}> Manage CToken Rewards </Heading>
{/* Select Asset */}
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="center"
mt={1}
>
{pool.assets.map(
(asset: USDPricedFuseAsset, index: number, array: any[]) => {
return (
<Box
pr={index === array.length - 1 ? 4 : 2}
key={asset.cToken}
flexShrink={0}
>
<DashboardBox
as="button"
onClick={() => setSelectedAsset(asset)}
{...(asset.cToken === selectedAsset?.cToken
? activeStyle
: noop)}
>
<Center expand px={4} py={1} fontWeight="bold">
{asset.underlyingSymbol}
</Center>
</DashboardBox>
</Box>
);
}
)}
</Row>
{/* Change Supply Speed */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
py={3}
>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
>
<NumberInput
step={0.1}
min={0}
onChange={(supplySpeed) => {
console.log({ supplySpeed });
setSupplySpeed(parseFloat(supplySpeed));
}}
>
<NumberInputField
width="100%"
textAlign="center"
placeholder={"0 " + tokenData?.symbol}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Button
onClick={changeSupplySpeed}
bg="black"
disabled={changingSpeed || !isAdmin}
>
{changingSpeed ? <Spinner /> : "Set"}
</Button>
</Row>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
>
<Text>
Supply Speed:{" "}
{(parseFloat(supplySpeedForCToken) / 1e18).toFixed(4)}
</Text>
</Row>
</Column>
{/* Change Borrow Speed */}
<Column
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
py={3}
>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
>
<NumberInput
step={0.1}
min={0}
onChange={(borrowSpeed) => {
console.log({ borrowSpeed });
setBorrowSpeed(parseFloat(borrowSpeed));
}}
>
<NumberInputField
width="100%"
textAlign="center"
placeholder={"0 " + tokenData?.symbol}
/>
<NumberInputStepper>
<NumberIncrementStepper />
<NumberDecrementStepper />
</NumberInputStepper>
</NumberInput>
<Button
onClick={changeBorrowSpeed}
bg="black"
disabled={changingBorrowSpeed || !isAdmin}
>
{changingBorrowSpeed ? <Spinner /> : "Set"}
</Button>
</Row>
<Row
mainAxisAlignment="flex-start"
crossAxisAlignment="flex-start"
>
<Text>
Borrow Speed:{" "}
{(parseFloat(borrowSpeedForCToken) / 1e18).toFixed(2)}
</Text>
</Row>
</Column>
</Column>
) : (
<Center p={4}>
<Text fontWeight="bold">
Add CTokens to this pool to configure their rewards.
</Text>
</Center>
)}
</Column>
</ModalContent>
</Modal>
);
}