@chakra-ui/react#FormLabel JavaScript Examples
The following examples show how to use
@chakra-ui/react#FormLabel.
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: Form.js From web-client with Apache License 2.0 | 6 votes |
DocumentForm = ({ document, onFormSubmit, documentSetter: setNote, isEditForm = false }) => {
const onFormInputChange = ev => {
const target = ev.target;
const name = target.name;
const value = target.value;
setNote({
...document, [name]: value
});
};
return <form onSubmit={onFormSubmit}>
<FormControl isRequired>
<FormLabel htmlFor="title">Title</FormLabel>
<Input type="text" name="title" id="title" value={document.title || ""} onChange={onFormInputChange} autoFocus />
</FormControl>
<FormControl isRequired>
<FormLabel htmlFor="content">Content (markdown supported)</FormLabel>
<MarkdownEditor name="content" style={{ width: '100%' }} required value={document.content || ""}
onChange={onFormInputChange} /><br />
</FormControl>
<FormControl>
<FormLabel htmlFor="visibility">Visibility</FormLabel>
<Select name="visibility" id="visibility" value={document.visibility} onChange={onFormInputChange} required>
<option value="private">Private</option>
<option value="public">Public</option>
</Select>
</FormControl>
<PrimaryButton type="submit">{isEditForm ? "Update" : "Create"}</PrimaryButton>
</form>
}
Example #2
Source File: Form.js From web-client with Apache License 2.0 | 6 votes |
VulnerabilityCategoryForm = ({ category, onFormSubmit, categorySetter: setCategory }) => {
const [categories] = useFetch('/vulnerabilities/categories?parentsOnly=true');
const onFormInputChange = ev => {
const target = ev.target;
const name = target.name;
const value = target.value === "" ? null : target.value;
setCategory({ ...category, [name]: value });
};
return <form id="vulnerability_category_form" onSubmit={onFormSubmit}>
<FormControl id="parent_id" isRequired>
<FormLabel>Parent category</FormLabel>
{categories && <Select name="parent_id" value={category.parent_id} onChange={onFormInputChange}>
<option>(none)</option>
{categories.filter(category => category.parent_id === null).map(category => <option key={category.id} value={category.id}>{category.name}</option>)}
</Select>}
</FormControl>
<FormControl id="name" isRequired>
<FormLabel>Name</FormLabel>
<Input name="name" autoFocus value={category.name} onChange={onFormInputChange} />
</FormControl>
<FormControl id="description">
<FormLabel>Description</FormLabel>
<Input name="description" value={category.description} onChange={onFormInputChange} />
</FormControl>
</form>
}
Example #3
Source File: Form.js From web-client with Apache License 2.0 | 6 votes |
TargetForm = ({ newTarget, onFormSubmit, targetSetter: setTarget }) => {
const onFormChange = ev => {
const target = ev.target;
const name = target.name;
let value = target.value;
if ('tags' === name) {
value = JSON.stringify(value.split(','));
}
setTarget({ ...newTarget, [name]: value });
};
return <div>
<form onSubmit={onFormSubmit}>
<FormControl id="name" isRequired>
<FormLabel>Name</FormLabel>
<Input name="name" placeholder="e.g. 127.0.0.1" onChange={onFormChange} isRequired autoFocus />
</FormControl>
<FormControl id="tags">
<FormLabel>Tags</FormLabel>
<Input name="tags" placeholder="e.g. linux,production" onChange={onFormChange} />
</FormControl>
<FormControl id="kind" isRequired>
<FormLabel>Kind</FormLabel>
<Select name="kind" onChange={onFormChange}>
{TargetKinds.map((targetKind, index) =>
<option key={index} value={targetKind.value}>{targetKind.description}</option>
)}
</Select>
</FormControl>
</form>
</div>
}
Example #4
Source File: Form.js From web-client with Apache License 2.0 | 6 votes |
NotesForm = ({ note, onFormSubmit, noteSetter: setNote }) => {
const onFormInputChange = ev => {
const target = ev.target;
const name = target.name;
const value = target.value;
setNote({ ...note, [name]: value });
};
return <form onSubmit={onFormSubmit}>
<FormControl id="content" isRequired>
<FormLabel>Content</FormLabel>
<Textarea name="content" style={{ width: '100%' }} value={note.content}
onChange={onFormInputChange} autoFocus /><br />
</FormControl>
<FormControl id="visibility" isRequired>
<FormLabel>Visibility</FormLabel>
<Select name="visibility" value={note.visibility} onChange={onFormInputChange}>
<option value="private">Private</option>
<option value="public">Public</option>
</Select>
</FormControl>
</form>
}
Example #5
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 #6
Source File: SignIn.js From grandcast.fm with Apache License 2.0 | 6 votes |
SignIn = () => {
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const { signIn } = useAuth()
function onSubmit(e) {
e.preventDefault()
signIn({ username, password })
}
return (
<div>
<FormControl b="1px" id="signin">
<FormLabel m={4}>Sign In</FormLabel>
<Input
m={4}
type="text"
placeholder="username"
onChange={(e) => setUsername(e.target.value)}
></Input>
<Input
m={4}
type="password"
placeholder="password"
onChange={(e) => setPassword(e.target.value)}
></Input>
<Button m={4} w="100%" onClick={onSubmit} type="submit">
Log In
</Button>
</FormControl>
</div>
)
}
Example #7
Source File: components.js From idena-web with MIT License | 6 votes |
export function VotingInlineFormControl({
htmlFor,
label,
tooltip,
children,
...props
}) {
return (
<FormControl display="inline-flex" {...props}>
{tooltip ? (
<FormLabel htmlFor={htmlFor} color="muted" py={2} minW={32} w={32}>
<Tooltip label={tooltip} placement="top" zIndex="tooltip">
<Text
as="span"
borderBottomStyle="dotted"
borderBottomWidth="1px"
borderBottomColor="muted"
cursor="help"
>
{label}
</Text>
</Tooltip>
</FormLabel>
) : (
<FormLabel htmlFor={htmlFor} color="muted" py={2} minW={32} w={32}>
{label}
</FormLabel>
)}
<Box w="md">{children}</Box>
</FormControl>
)
}
Example #8
Source File: components.js From idena-web with MIT License | 6 votes |
export function OracleFormControl({label, children, ...props}) {
return (
<FormControl {...props}>
<FormLabel color="brandGray.500" mb={2}>
{label}
</FormLabel>
{children}
</FormControl>
)
}
Example #9
Source File: Send.js From web-client with Apache License 2.0 | 5 votes |
SendReport = () => {
const navigate = useNavigate();
const { projectId } = useParams();
const [project] = useFetch(`/projects/${projectId}`)
const [revisions] = useFetch(`/reports?projectId=${projectId}`)
const [deliverySettings, setDeliverySettings] = useState({
report_id: null,
recipients: null,
subject: "[CONFIDENTIAL] Security report attached",
body: "Please review attachment containing a security report."
})
const handleSend = async (ev) => {
ev.preventDefault();
secureApiFetch(`/reports/${deliverySettings.report_id}/send`, { method: 'POST', body: JSON.stringify(deliverySettings) })
.then(() => {
navigate(`/projects/${project.id}/report`);
})
.catch(err => {
console.error(err);
})
}
const handleFormChange = ev => {
const target = ev.target;
const name = target.name;
const value = target.value;
setDeliverySettings({ ...deliverySettings, [name]: value });
};
useEffect(() => {
if (revisions && deliverySettings.report_id === null)
setDeliverySettings({ ...deliverySettings, report_id: revisions[0].id })
}, [revisions, deliverySettings]);
if (!project) return <Loading />
return <div>
<PageTitle value="Send report" />
<div className='heading'>
<Breadcrumb>
<Link to="/projects">Projects</Link>
{project && <Link to={`/projects/${project.id}`}>{project.name}</Link>}
{project && <Link to={`/projects/${project.id}/report`}>Report</Link>}
</Breadcrumb>
</div>
<form onSubmit={handleSend}>
<Title title='Send report' />
<FormControl isRequired>
<FormLabel for="reportId">Revision</FormLabel>
<Select id="reportId" name="report_id" onChange={handleFormChange}>
{revisions && revisions.map(revision => <option value={revision.id}>{revision.version_name}</option>)}
</Select>
</FormControl>
<FormControl isRequired>
<FormLabel>Recipients</FormLabel>
<Input type="text" name="recipients" onChange={handleFormChange} autoFocus
placeholder="[email protected]" />
<FormHelperText>Comma separated list of email addresses.</FormHelperText>
</FormControl>
<FormControl isRequired>
<FormLabel>Subject</FormLabel>
<Input type="text" name="subject" onChange={handleFormChange}
value={deliverySettings.subject} />
</FormControl>
<FormControl isRequired>
<FormLabel>Body</FormLabel>
<Textarea name="body" onChange={handleFormChange} value={deliverySettings.body} />
</FormControl>
<PrimaryButton type="submit">Send</PrimaryButton>
</form>
</div>
}
Example #10
Source File: ModalDialog.js From web-client with Apache License 2.0 | 5 votes |
ReportModalDialog = ({ isOpen, onSubmit, onCancel }) => {
const fileRef = useRef();
const emptyReportTemplate = {
version_name: "",
version_description: null,
resultFile: null,
}
const [reportTemplate, setReportTemplate] = useState(emptyReportTemplate)
const onCreateReportFormSubmit = ev => {
ev.preventDefault();
const formData = new FormData();
formData.append('version_name', reportTemplate.version_name);
formData.append('version_description', reportTemplate.version_description);
formData.append('resultFile', fileRef.current.files[0]);
secureApiFetch(`/reports/templates`, { method: 'POST', body: formData })
.then(() => {
onSubmit();
actionCompletedToast(`The report template "${reportTemplate.version_name}" has been added.`);
})
.catch(err => {
errorToast(err);
})
.finally(() => {
setReportTemplate(emptyReportTemplate)
})
}
const onFormChange = ev => {
setReportTemplate({ ...reportTemplate, [ev.target.name]: ev.target.value })
}
return <Modal size="xl" isOpen={isOpen} onClose={onCancel}>
<ModalOverlay />
<ModalContent>
<ModalHeader><h4>New report template details</h4></ModalHeader>
<ModalCloseButton />
<ModalBody>
<form id="reportTemplateForm" onSubmit={onCreateReportFormSubmit}>
<FormControl isRequired>
<FormLabel>Version name</FormLabel>
<Input type="text" name="version_name" onChange={onFormChange} autoFocus />
</FormControl>
<FormControl>
<FormLabel>Version description</FormLabel>
<Input type="text" name="version_description" onChange={onFormChange} />
</FormControl>
<FormControl isRequired>
<FormLabel>File</FormLabel>
<Input type="file" ref={fileRef} name="resultFile" onChange={onFormChange} />
</FormControl>
</form>
</ModalBody>
<ModalFooter>
<Button onClick={onCancel} mr={3}>Cancel</Button>
<Button form="reportTemplateForm" type="submit" colorScheme="blue">Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #11
Source File: Preferences.js From web-client with Apache License 2.0 | 5 votes |
UserPreferences = () => {
const user = Auth.getLoggedInUser();
user.preferences = initialiseUserPreferences(user);
const timezones = CountriesTimezones.getAllTimezones();
const timezoneKeys = Object.keys(timezones).sort();
const { setTheme } = useContext(ThemeContext);
const { setColorMode } = useColorMode();
const [formValues, setFormValues] = useState({
timezone: user.timezone,
theme: user.preferences["web-client.theme"]
});
const updateFormValues = ev => {
setFormValues({ ...formValues, [ev.target.name]: ev.target.value });
}
const onFormSubmit = ev => {
ev.preventDefault();
user.timezone = formValues.timezone;
user.preferences = { ...initialiseUserPreferences(user), "web-client.theme": formValues.theme };
secureApiFetch(`/users/${user.id}`, {
method: 'PATCH',
body: JSON.stringify({ timezone: formValues.timezone, preferences: user.preferences })
})
.then(() => {
setTheme(theme => {
setThemeColors(formValues.theme);
setColorMode(formValues.theme);
return formValues.theme;
});
localStorage.setItem('user', JSON.stringify(user));
actionCompletedToast("Your preferences have been saved.");
})
.catch(err => console.error(err));
}
return <>
<PageTitle value="Preferences" />
<div className='heading'>
<Breadcrumb />
</div>
<Title type='User' title='Preferences' icon={<IconPreferences />} />
<form onSubmit={onFormSubmit}>
<FormControl>
<FormLabel>Theme</FormLabel>
<Select name="theme" onChange={updateFormValues} defaultValue={formValues.theme || "dark"}>
<option value="dark">Dark</option>
<option value="light">Light</option>
</Select>
</FormControl>
<FormControl>
<FormLabel>Timezone</FormLabel>
<Select name="timezone" onChange={updateFormValues} defaultValue={user.timezone}>
{timezoneKeys.map((key, index) =>
<option key={index} value={timezones[key].name}>{timezones[key].name}</option>
)}
</Select>
</FormControl>
<Primary type="submit">Save</Primary>
</form>
</>
}
Example #12
Source File: BuilderProfileCard.jsx From scaffold-directory with MIT License | 4 votes |
BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvider, fetchBuilder, userRole }) => {
const address = useUserAddress(userProvider);
const ens = useDisplayAddress(mainnetProvider, builder?.id);
const [updatedSocials, setUpdatedSocials] = useState({});
const [isUpdatingReachedOutFlag, setIsUpdatingReachedOutFlag] = useState(false);
const [isUpdatingSocials, setIsUpdatingSocials] = useState(false);
const { isOpen, onOpen, onClose } = useDisclosure();
const { hasCopied, onCopy } = useClipboard(builder?.id);
const { borderColor, secondaryFontColor } = useCustomColorModes();
const shortAddress = ellipsizedAddress(builder?.id);
const hasEns = ens !== shortAddress;
const toast = useToast({ position: "top", isClosable: true });
const toastVariant = useColorModeValue("subtle", "solid");
const joinedDate = new Date(builder?.creationTimestamp);
const joinedDateDisplay = joinedDate.toLocaleString("default", { month: "long" }) + " " + joinedDate.getFullYear();
// INFO: conditional chaining and coalescing didn't work when also checking the length
const hasProfileLinks = builder?.socialLinks ? Object.keys(builder.socialLinks).length !== 0 : false;
const isAdmin = userRole === USER_ROLES.admin;
useEffect(() => {
if (builder) {
setUpdatedSocials(builder.socialLinks ?? {});
}
}, [builder]);
const handleUpdateSocials = async () => {
setIsUpdatingSocials(true);
// Avoid sending socials with empty strings.
const socialLinkCleaned = Object.fromEntries(Object.entries(updatedSocials).filter(([_, value]) => !!value));
const invalidSocials = validateSocials(socialLinkCleaned);
if (invalidSocials.length !== 0) {
toast({
description: `The usernames for the following socials are not correct: ${invalidSocials
.map(([social]) => social)
.join(", ")}`,
status: "error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
let signMessage;
try {
signMessage = await getUpdateSocialsSignMessage(address);
} catch (error) {
toast({
description: " Sorry, the server is overloaded. ???",
status: "error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
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,
});
setIsUpdatingSocials(false);
return;
}
try {
await postUpdateSocials(address, signature, socialLinkCleaned);
} catch (error) {
if (error.status === 401) {
toast({
status: "error",
description: "Access error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
toast({
status: "error",
description: "Can't update your socials. Please try again.",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
toast({
description: "Your social links have been updated",
status: "success",
variant: toastVariant,
});
fetchBuilder();
setIsUpdatingSocials(false);
onClose();
};
const handleUpdateReachedOutFlag = async reachedOut => {
setIsUpdatingReachedOutFlag(true);
let signMessage;
try {
signMessage = await getUpdateReachedOutFlagSignMessage(builder.id, reachedOut);
} catch (error) {
toast({
description: " Sorry, the server is overloaded. ???",
status: "error",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
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,
});
setIsUpdatingReachedOutFlag(false);
return;
}
try {
await postUpdateReachedOutFlag(address, builder.id, reachedOut, signature);
} catch (error) {
if (error.status === 401) {
toast({
status: "error",
description: "Access error",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
toast({
status: "error",
description: "Can't update the reached out flag. Please try again.",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
toast({
description: 'Updated "reached out" flag successfully',
status: "success",
variant: toastVariant,
});
fetchBuilder();
setIsUpdatingReachedOutFlag(false);
};
return (
<>
<BuilderProfileCardSkeleton isLoaded={!!builder}>
{() => (
/* delay execution */
<Flex
borderRadius="lg"
borderColor={borderColor}
borderWidth={1}
justify={{ base: "space-around", xl: "center" }}
direction={{ base: "row", xl: "column" }}
p={4}
pb={6}
maxW={{ base: "full", lg: "50%", xl: 60 }}
margin="auto"
>
<Link as={RouteLink} to={`/builders/${builder.id}`}>
<QRPunkBlockie
withQr={false}
address={builder.id?.toLowerCase()}
w={52}
borderRadius="lg"
margin="auto"
/>
</Link>
<Flex alignContent="center" direction="column" mt={4}>
{hasEns ? (
<>
<Text fontSize="2xl" fontWeight="bold" textAlign="center">
{ens}
</Text>
<Text textAlign="center" mb={4} color={secondaryFontColor}>
{shortAddress}{" "}
<Tooltip label={hasCopied ? "Copied!" : "Copy"} closeOnClick={false}>
<CopyIcon cursor="pointer" onClick={onCopy} />
</Tooltip>
</Text>
</>
) : (
<Text fontSize="2xl" fontWeight="bold" textAlign="center" mb={8}>
{shortAddress}{" "}
<Tooltip label={hasCopied ? "Copied!" : "Copy"} closeOnClick={false}>
<CopyIcon cursor="pointer" onClick={onCopy} />
</Tooltip>
</Text>
)}
{isAdmin && (
<Center mb={4}>
{builder.reachedOut ? (
<Badge variant="outline" colorScheme="green" alignSelf="center">
Reached Out
</Badge>
) : (
<Button
colorScheme="green"
size="xs"
onClick={() => handleUpdateReachedOutFlag(true)}
isLoading={isUpdatingReachedOutFlag}
alignSelf="center"
>
Mark as reached out
</Button>
)}
</Center>
)}
<Divider mb={6} />
{hasProfileLinks ? (
<Flex mb={4} justifyContent="space-evenly" alignItems="center">
{Object.entries(builder.socialLinks)
.sort(bySocialWeight)
.map(([socialId, socialValue]) => (
<SocialLink id={socialId} value={socialValue} />
))}
</Flex>
) : (
isMyProfile && (
<Alert mb={3} status="warning">
<Text style={{ fontSize: 11 }}>
You haven't set your socials{" "}
<Tooltip label="It's our way of reaching out to you. We could sponsor you an ENS, offer to be part of a build or set up an ETH stream for you.">
<QuestionOutlineIcon />
</Tooltip>
</Text>
</Alert>
)
)}
{isMyProfile && (
<Button mb={3} size="xs" variant="outline" onClick={onOpen}>
Update socials
</Button>
)}
<Text textAlign="center" color={secondaryFontColor}>
Joined {joinedDateDisplay}
</Text>
</Flex>
</Flex>
)}
</BuilderProfileCardSkeleton>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Update your socials</ModalHeader>
<ModalCloseButton />
<ModalBody p={6}>
{Object.entries(socials).map(([socialId, socialData]) => (
<FormControl id="socialId" key={socialId} mb={3}>
<FormLabel htmlFor={socialId} mb={0}>
<strong>{socialData.label}:</strong>
</FormLabel>
<Input
type="text"
name={socialId}
value={updatedSocials[socialId] ?? ""}
placeholder={socialData.placeholder}
onChange={e => {
const value = e.target.value;
setUpdatedSocials(prevSocials => ({
...prevSocials,
[socialId]: value,
}));
}}
/>
</FormControl>
))}
<Button colorScheme="blue" onClick={handleUpdateSocials} isLoading={isUpdatingSocials} isFullWidth mt={4}>
Update
</Button>
</ModalBody>
</ModalContent>
</Modal>
</>
);
}
Example #13
Source File: ChallengeSubmission.jsx From scaffold-directory with MIT License | 4 votes |
// ToDo. on-line form validation
export default function ChallengeSubmission({ challenge, serverUrl, address, userProvider }) {
const { challengeId } = useParams();
const history = useHistory();
const toast = useToast({ position: "top", isClosable: true });
const [isSubmitting, setIsSubmitting] = useState(false);
const [deployedUrl, setDeployedUrl] = useState("");
const [contractUrl, setContractUrl] = useState("");
const [hasErrorField, setHasErrorField] = useState({ deployedUrl: false, contractUrl: false });
const onFinish = async () => {
if (!deployedUrl || !contractUrl) {
toast({
status: "error",
description: "Both fields are required",
});
return;
}
if (!isValidUrl(deployedUrl) || !isValidUrl(contractUrl)) {
toast({
status: "error",
title: "Please provide a valid URL",
description: "Valid URLs start with http:// or https://",
});
setHasErrorField({
deployedUrl: !isValidUrl(deployedUrl),
contractUrl: !isValidUrl(contractUrl),
});
return;
}
setIsSubmitting(true);
let signMessage;
try {
const signMessageResponse = await axios.get(serverUrl + `/sign-message`, {
params: {
messageId: "challengeSubmit",
address,
challengeId,
},
});
signMessage = JSON.stringify(signMessageResponse.data);
} catch (error) {
toast({
description: "Can't get the message to sign. Please try again",
status: "error",
});
setIsSubmitting(false);
return;
}
let signature;
try {
signature = await userProvider.send("personal_sign", [signMessage, address]);
} catch (error) {
toast({
status: "error",
description: "The signature was cancelled",
});
console.error(error);
setIsSubmitting(false);
return;
}
try {
await axios.post(
serverUrl + serverPath,
{
challengeId,
deployedUrl,
contractUrl,
signature,
},
{
headers: {
address,
},
},
);
} catch (error) {
toast({
status: "error",
description: "Submission Error. Please try again.",
});
console.error(error);
setIsSubmitting(false);
return;
}
toast({
status: "success",
description: "Challenge submitted!",
});
setIsSubmitting(false);
history.push("/portfolio");
};
if (!address) {
return (
<Text color="orange.400" className="warning" align="center">
Connect your wallet to submit this Challenge.
</Text>
);
}
return (
<div>
<Heading as="h2" size="md" mb={4}>
{challenge.label}
</Heading>
{challenge.isDisabled ? (
<Text color="orange.400" className="warning">
This challenge is disabled.
</Text>
) : (
<form name="basic" autoComplete="off">
<FormControl id="deployedUrl" isRequired>
<FormLabel>
Deployed URL{" "}
<Tooltip label="Your deployed challenge URL on surge / s3 / ipfs ">
<QuestionOutlineIcon ml="2px" />
</Tooltip>
</FormLabel>
<Input
type="text"
name="deployedUrl"
value={deployedUrl}
placeholder="https://your-site.surge.sh"
onChange={e => {
setDeployedUrl(e.target.value);
if (hasErrorField.deployedUrl) {
setHasErrorField(prevErrorsFields => ({
...prevErrorsFields,
deployedUrl: false,
}));
}
}}
borderColor={hasErrorField.deployedUrl && "red.500"}
/>
</FormControl>
<FormControl id="contractUrl" isRequired mt={4}>
<FormLabel>
Etherscan Contract URL{" "}
<Tooltip label="Your verified contract URL on Etherscan">
<QuestionOutlineIcon ml="2px" />
</Tooltip>
</FormLabel>
<Input
type="text"
name="contractUrl"
value={contractUrl}
placeholder="https://etherscan.io/address/your-contract-address"
onChange={e => {
setContractUrl(e.target.value);
if (hasErrorField.contractUrl) {
setHasErrorField(prevErrorsFields => ({
...prevErrorsFields,
contractUrl: false,
}));
}
}}
borderColor={hasErrorField.contractUrl && "red.500"}
/>
</FormControl>
<div className="form-item">
<Button colorScheme="blue" onClick={onFinish} isLoading={isSubmitting} mt={4} isFullWidth>
Submit
</Button>
</div>
</form>
)}
</div>
);
}
Example #14
Source File: MakeClaim.js From DAOInsure with MIT License | 4 votes |
function MakeClaim() {
const [currentImage, setCurrentImage] = useState(undefined);
const [images, setImages] = useState([]);
const [isPageLoading, setIsPageLoading] = useState(false);
const { textileClient } = useContext(AppContext);
const [claimTitle, setClaimTitle] = useState();
const [claimSummary, setClaimSummary] = useState();
const [dateOfIncident, setDateOfIncident] = useState();
const [startTime, setStartTime] = useState();
const web3Context = useContext(Web3Context);
const {
createProposal,
signerAddress,
claimableAmount,
getClaimableAmount,
} = web3Context;
useEffect(() => {
getClaimableAmount();
}, []);
const handleImage = async (e) => {
console.log("uploading");
let file = e.target.files[0];
try {
let result = await uploadToSlate(file);
setImages([
...images,
{
isUploading: false,
url: `https://slate.textile.io/ipfs/${result.data.cid}`,
},
]);
setCurrentImage(`https://slate.textile.io/ipfs/${result.data.cid}`);
console.log("uploaded");
} catch (e) {
console.log(e);
}
};
const handleCurrentImage = (e) => {
e.preventDefault();
setCurrentImage(e.target.src);
};
const handleInputChange = (e, setter) => {
e.preventDefault();
setter(e.target.value);
};
const handleClaimSubmit = async (e) => {
e.preventDefault();
let imageUrls = images.map((image) => {
return image.url;
});
let claimObj = {
images: imageUrls,
claimTitle,
claimSummary,
dateOfIncident,
claimAmount: claimableAmount,
author: signerAddress,
};
console.log(claimObj);
// tried using fleek instead of threadDB.
// let response = await fleekStorage.upload({
// apiKey: "3aFyv9UlnpyVvuhdoy+WMA==",
// apiSecret: "vUREhYRSH5DP8WehKP+N8jTLoOJUBw+RA9TPLUKneK8=",
// key: uuidv4(),
// data: JSON.stringify(claimObj),
// });
// adding claim data to threadDB.
let response = await addToThread(
textileClient,
"bafkyspsyykcninhqn4ht6d6jeqmzq4cepy344akmkhjk75dmw36wq4q",
"claimsData",
claimObj
);
// create proposal on contract basically store the hash.
createProposal(
claimTitle,
(new Date(dateOfIncident).getTime() / 1000).toString(),
response.hash
);
};
return (
<Grid
paddingBottom='20px'
pt='20px'
height='100%'
px='250px'
width='100%'
templateColumns='2fr 1fr'
gridGap={5}
alignItems='flex-start'>
<VStack width='100%' alignItems='flex-start'>
<Skeleton isLoaded={!isPageLoading}>
<Heading as='h4' fontSize='28px'>
Make a Claim
</Heading>
</Skeleton>
<form style={{ width: "100%" }}>
<VStack width='100%' spacing={5} alignItems='flex-start'>
<input
multiple
onChange={(e) => handleImage(e)}
type='file'
style={{ display: "none" }}
id='image-input'
accept='image/*'
/>
{images.length == 0 ? (
isPageLoading ? (
<Spinner
colorScheme='whatsapp'
color='whatsapp.500'
alignSelf='center'
/>
) : (
<Box
cursor='pointer'
as='label'
htmlFor='image-input'
px='35px'
width='100%'
borderRadius='10px'
height='70px'
borderWidth='1px'
borderStyle='solid'
borderColor='whatsapp.500'>
<VStack
height='100%'
width='100%'
justifyContent='center'>
<TiPlus style={{ fill: "#22C35E" }} />
<Text fontWeight='600' color='#22C35E'>
Image
</Text>
</VStack>
</Box>
)
) : (
<>
<Box
mt='10px !important'
boxShadow='lg'
borderRadius='10px'>
<Image
borderRadius='10px'
src={currentImage}
/>
</Box>
<HStack width='100%' overflowX='scroll'>
{images.map((image, index) => {
return image.isUploading ? (
<Spinner key={index} />
) : (
<Image
key={image.url}
onClick={(e) => {
handleCurrentImage(e);
}}
borderRadius='10px'
height='70px'
src={image.url}
/>
);
})}
<Box
cursor='pointer'
as='label'
htmlFor='image-input'
px='35px'
borderRadius='10px'
height='70px'
borderWidth='1px'
borderStyle='solid'
borderColor='whatsapp.500'>
<VStack
height='100%'
width='100%'
justifyContent='center'>
<TiPlus
style={{ fill: "#22C35E" }}
/>
<Text
fontWeight='600'
color='#22C35E'>
Image
</Text>
</VStack>
</Box>
</HStack>
</>
)}
<VStack spacing={5} width='100%'>
<FormControl isRequired>
<Skeleton isLoaded={!isPageLoading}>
<FormLabel>Claim Title</FormLabel>
</Skeleton>
<Skeleton isLoaded={!isPageLoading}>
<Input
onChange={(e) =>
handleInputChange(e, setClaimTitle)
}
/>
</Skeleton>
</FormControl>
<FormControl isRequired>
<Skeleton isLoaded={!isPageLoading}>
<FormLabel>Summary of Incident</FormLabel>
</Skeleton>
<Skeleton isLoaded={!isPageLoading}>
<Textarea
onChange={(e) =>
handleInputChange(
e,
setClaimSummary
)
}
row='10'
/>
</Skeleton>
<Skeleton isLoaded={!isPageLoading}>
<FormHelperText>
Try to precise
</FormHelperText>
</Skeleton>
</FormControl>
<VStack width='100%'>
<HStack width='100%'>
<FormControl isRequired>
<Skeleton isLoaded={!isPageLoading}>
<FormLabel>
Date of Incident
</FormLabel>
</Skeleton>
<Skeleton isLoaded={!isPageLoading}>
<Input
onChange={(e) =>
handleInputChange(
e,
setDateOfIncident
)
}
type='date'
/>
</Skeleton>
</FormControl>
</HStack>
</VStack>
<Button
onClick={(e) => handleClaimSubmit(e)}
isLoading={isPageLoading}
mt='30px !important'
width='100%'
textTransform='uppercase'
type='submit'
colorScheme='whatsapp'>
Submit Claim
</Button>
</VStack>
</VStack>
</form>
</VStack>
<VStack width='100%'>
<Card isLoading={isPageLoading} cardTitle='Claimable Amount'>
<Skeleton isLoaded={!isPageLoading}>
<Heading
textColor='whatsapp.500'
fontSize='24px'
as='h3'>
{parseFloat(claimableAmount).toFixed(6)} DAI
</Heading>
</Skeleton>
</Card>
</VStack>
</Grid>
);
}
Example #15
Source File: ModalDialog.js From web-client with Apache License 2.0 | 4 votes |
ReportVersionModalDialog = ({ projectId, isOpen, onSubmit, onCancel }) => {
const defaultFormValues = { reportTemplateId: 0, name: "", description: "" };
const [formValues, setFormValues] = useState(defaultFormValues);
const [templates] = useFetch('/reports/templates');
const onFormValueChange = ev => {
ev.preventDefault();
setFormValues({ ...formValues, [ev.target.name]: ev.target.value });
};
const beforeCancelCallback = ev => {
setFormValues(defaultFormValues);
onCancel(ev);
}
const onFormSubmit = ev => {
ev.preventDefault();
const params = {
projectId: projectId,
reportTemplateId: formValues.reportTemplateId,
name: formValues.name,
description: formValues.description
};
secureApiFetch(`/reports`, { method: 'POST', body: JSON.stringify(params) })
.then(() => {
onSubmit();
actionCompletedToast(`The report version "${formValues.name}" has been added.`);
})
.catch(err => {
console.error(err);
})
.finally(() => {
setFormValues(defaultFormValues)
})
}
useEffect(() => {
if (templates !== null && templates.length > 0) {
setFormValues((prev) => ({ ...prev, reportTemplateId: templates[0].id }))
}
}, [templates]);
return <Modal size="xl" isOpen={isOpen} onClose={beforeCancelCallback}>
<ModalOverlay />
<ModalContent>
<ModalHeader><HStack><TargetIcon style={{ width: '24px' }} /> <h4>New report version details</h4></HStack></ModalHeader>
<ModalCloseButton />
<ModalBody>
<form id="reportVersionReportForm" onSubmit={onFormSubmit} className="crud" style={{ marginTop: '20px' }}>
<FormControl isRequired>
<FormLabel>Template</FormLabel>
{templates && <Select name="reportTemplateId" value={formValues.reportTemplateId} onChange={onFormValueChange}>
{templates.map(template => <option key={template.id} value={template.id}>{template.version_name}</option>)}
</Select>}
</FormControl>
<FormControl isRequired>
<FormLabel>Name</FormLabel>
<Input type="text" name="name" value={formValues.name} onChange={onFormValueChange}
placeholder="eg 1.0, 202103" autoFocus />
</FormControl>
<FormControl isRequired>
<FormLabel>Description</FormLabel>
<Input type="text" name="description" value={formValues.description}
onChange={onFormValueChange}
placeholder="eg Initial version, Draft"
/>
</FormControl>
</form>
</ModalBody>
<ModalFooter>
<Button onClick={beforeCancelCallback} mr={3}>Cancel</Button>
<Button form="reportVersionReportForm" type="submit" colorScheme="blue">Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #16
Source File: ProductAddEdit.js From react-sample-projects with MIT License | 4 votes |
ProductAddEdit = () => {
const categories = useSelector(state => state.product.categories);
const dispatch = useDispatch();
const navigate = useNavigate();
const initialValues = {
title: '',
price: '',
category: '',
description: '',
image: '',
};
const validationSchema = yup.object({
title: yup.string().required(),
price: yup.number().required(),
category: yup.string().required(),
description: yup.string().required(),
image: yup.string().url().required(),
});
const onFormSubmit = (values, actions) => {
actions.setSubmitting(false);
dispatch(addNewProduct(values));
navigate('/');
};
useEffect(() => {
dispatch(fetchCategories());
return () => {};
}, [dispatch]);
return (
<Box boxShadow="base" m={'auto'} width="clamp(300px, 60%, 100%)">
<Formik
initialValues={initialValues}
onSubmit={onFormSubmit}
validationSchema={validationSchema}
>
{props => (
<Form noValidate>
<VStack p={3} m="3">
<Box fontWeight="semibold" mt="1" as="h2" textAlign="left">
Add Product
</Box>
<Field name="title">
{({ field, form }) => (
<FormControl
isRequired
isInvalid={form.errors.title && form.touched.title}
>
<FormLabel htmlFor="title">Enter Title</FormLabel>
<Input
{...field}
type="text"
id="title"
placeholder="Enter Title"
/>
<ErrorMessage
name="title"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Field name="price">
{({ field, form }) => (
<FormControl
isRequired
isInvalid={form.errors.price && form.touched.price}
>
<FormLabel>Enter price</FormLabel>
<Input type="number" placeholder="Enter price" {...field} />
<ErrorMessage
name="price"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Field name="category">
{({ field, form }) => (
<FormControl
name="category"
isRequired
isInvalid={form.errors.category && form.touched.category}
>
<FormLabel>Enter category</FormLabel>
<Select placeholder="Select category" {...field}>
{categories.map((category, index) => (
<option key={index}>{category}</option>
))}
</Select>
<ErrorMessage
name="category"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Field name="description">
{({ field, form }) => (
<FormControl
name="description"
isRequired
isInvalid={
form.errors.description && form.touched.description
}
>
<FormLabel>Enter description</FormLabel>
<Textarea
{...field}
id="description"
placeholder="Enter description"
></Textarea>
<ErrorMessage
name="description"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Field name="image">
{({ field, form }) => (
<FormControl
name="image"
isRequired
isInvalid={form.errors.image && form.touched.image}
>
<FormLabel>Enter image</FormLabel>
<Input
type="url"
placeholder="Enter image url"
{...field}
/>
<ErrorMessage
name="image"
component={FormErrorMessage}
></ErrorMessage>
</FormControl>
)}
</Field>
<Button
mt={4}
colorScheme="teal"
type="submit"
isLoading={props.isSubmitting}
>
Add Product
</Button>
</VStack>
</Form>
)}
</Formik>
</Box>
);
}
Example #17
Source File: Form.js From web-client with Apache License 2.0 | 4 votes |
VulnerabilityForm = ({
isEditForm = false,
vulnerability,
vulnerabilitySetter: setVulnerability,
onFormSubmit
}) => {
const [initialised, setInitialised] = useState(false);
const [projects, setProjects] = useState(null);
const [categories, setCategories] = useState(null);
const [subCategories, setSubCategories] = useState(null);
const [targets, setTargets] = useState(null);
const [useOWASP, setMetrics] = useState(false);
useEffect(() => {
if (initialised) return;
Promise.all([
secureApiFetch(`/projects`, { method: 'GET' }),
secureApiFetch(`/vulnerabilities/categories`, { method: 'GET' }),
])
.then(resp => {
const [respA, respB] = resp;
return Promise.all([respA.json(), respB.json()]);
})
.then(([projects, categories]) => {
const defaultProjectId = projects.length ? projects[0].id : 0;
const projectId = isEditForm ? vulnerability.project_id : defaultProjectId;
setMetrics(isOwaspProject(projects, projectId))
var subcategories = null;
if (vulnerability.parent_category_id) {
secureApiFetch(`/vulnerabilities/categories/${vulnerability.parent_category_id}`, { method: 'GET' })
.then(response => response.json())
.then(json => {
subcategories = json;
})
}
secureApiFetch(`/targets?projectId=${projectId}`, { method: 'GET' })
.then(resp => resp.json())
.then(targets => {
unstable_batchedUpdates(() => {
setProjects(projects);
setCategories(categories);
setTargets(targets);
setVulnerability(prevVulnerability => {
let updatedVulnerability = prevVulnerability;
if (!idExists(projects, prevVulnerability.project_id)) {
updatedVulnerability.project_id = defaultProjectId;
}
if ((!idExists(categories, prevVulnerability.category_id)) && (!idExists(subcategories, prevVulnerability.category_id))) {
updatedVulnerability.category_id = categories[0].id;
}
if (!idExists(targets, vulnerability.target_id)) {
updatedVulnerability.target_id = null;
}
return updatedVulnerability;
})
setInitialised(true);
});
})
});
}, [initialised, isEditForm, setProjects, setCategories, setTargets, setMetrics, setVulnerability, vulnerability.target_id, vulnerability.project_id, vulnerability.parent_category_id, subCategories, setSubCategories]);
useEffect(() => {
if (!initialised) return;
if (vulnerability.parent_category_id) {
secureApiFetch(`/vulnerabilities/categories/${vulnerability.parent_category_id}`, { method: 'GET' })
.then(response => response.json())
.then(json => {
setSubCategories(json);
})
}
const projectId = vulnerability.project_id;
secureApiFetch(`/targets?projectId=${projectId}`, { method: 'GET' })
.then(resp => resp.json())
.then(targets => {
unstable_batchedUpdates(() => {
setTargets(targets);
if (isEditForm) { // Edit
if (!idExists(targets, vulnerability.target_id)) {
setVulnerability(prevVulnerability => {
return { ...prevVulnerability, target_id: 0 }
});
}
}
});
})
}, [initialised, isEditForm, setTargets, setVulnerability, vulnerability.target_id, vulnerability.project_id, vulnerability.parent_category_id]);
const idExists = (elements, id) => {
if (!elements) return false;
for (const el of elements) {
if (el.id === parseInt(id)) return true;
}
return false;
}
const isOwaspProject = (elements, id) => {
let metrics = ProjectVulnerabilityMetrics[0].id;
for (const el of elements) {
if (el.id === parseInt(id)) {
metrics = el.vulnerability_metrics;
}
}
return (ProjectVulnerabilityMetrics[1].id === metrics);
}
const onFormChange = ev => {
const target = ev.target;
const name = target.name;
let value = target.type === 'checkbox' ? target.checked : target.value;
if ('tags' === name) {
value = JSON.stringify(value.split(','));
}
if ('category_id' === name) {
if (value !== '(none)') {
secureApiFetch(`/vulnerabilities/categories/${value}`, { method: 'GET' })
.then(response => response.json())
.then(json => {
setSubCategories(json);
})
setVulnerability({ ...vulnerability, 'parent_category_id': value, [name]: value });
} else {
setVulnerability({ ...vulnerability, 'category_id': null });
}
} else if ('subcategory_id' === name) {
setVulnerability({ ...vulnerability, 'category_id': value });
} else {
setVulnerability({ ...vulnerability, [name]: value });
}
};
return <form onSubmit={onFormSubmit} className="crud">
<Accordion defaultIndex={0} allowToggle allowMultiple>
<AccordionItem index={0}>
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
Basic information
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<label>Properties
<div>
<Checkbox name="is_template" onChange={onFormChange} isChecked={vulnerability.is_template}>Is template</Checkbox>
</div>
</label>
<label>External ID
<Input type="text" name="external_id" value={vulnerability.external_id || ""} onChange={onFormChange} />
</label>
<label>Summary
<Input type="text" name="summary" value={vulnerability.summary || ""} onChange={onFormChange} required autoFocus />
</label>
<label>Description
<MarkdownEditor name="description" value={vulnerability.description || ""} onChange={onFormChange} />
</label>
<label>External references
<MarkdownEditor name="external_refs" value={vulnerability.external_refs || ""} onChange={onFormChange} />
</label>
<label>Category
<Select name="category_id" value={vulnerability.parent_category_id || ""} onChange={onFormChange} required>
<option>(none)</option>
{categories && categories.map(cat =>
<option key={cat.id} value={cat.id}>{cat.name}</option>
)}
</Select>
</label>
<label>Subcategory
<Select name="subcategory_id" value={vulnerability.category_id || ""} onChange={onFormChange} required>
<option>(none)</option>
{subCategories && subCategories.map(subcat =>
<option key={subcat.id} value={subcat.id}>{subcat.name}</option>
)}
</Select>
</label>
<FormControl id="visibility" isRequired>
<FormLabel>Visibility</FormLabel>
<Select name="visibility" value={vulnerability.visibility || ""} onChange={onFormChange}>
<option value="public">Public</option>
<option value="private">Private</option>
</Select>
<FormHelperText>Private makes this vulnerability not visible to the client.</FormHelperText>
</FormControl>
<label>Risk
<Select name="risk" value={vulnerability.risk || ""} onChange={onFormChange} required>
{Risks.map(risk =>
<option key={risk.id} value={risk.id}>{risk.name}</option>
)}
</Select>
</label>
<label>Tags
<Input type="text" name="tags" onChange={onFormChange} value={vulnerability.tags ? JSON.parse(vulnerability.tags).join(',') : ''} />
</label>
<label>Proof of concept
<MarkdownEditor name="proof_of_concept" value={vulnerability.proof_of_concept || ""} onChange={onFormChange} />
</label>
<label>Impact
<MarkdownEditor name="impact" value={vulnerability.impact || ""} onChange={onFormChange} />
</label>
{
!useOWASP && <>
<label>CVSS score
<Input type="number" step="0.1" min="0" max="10" name="cvss_score" value={vulnerability.cvss_score || ""}
onChange={onFormChange} />
</label>
<label><span><CvssAbbr /> vector</span>
<Input type="text" name="cvss_vector" value={vulnerability.cvss_vector || ""} onChange={onFormChange} placeholder="eg: AV:N/AC:L/Au:S/C:P/I:P/A:N" />
</label>
</>
}
</AccordionPanel>
</AccordionItem>
{useOWASP &&
<AccordionItem>
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
Owasp Risk Rating calculator
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<label>Owasp Risk Rating</label>
<OwaspRR vulnerability={vulnerability} vulnerabilitySetter={setVulnerability} />
</AccordionPanel>
</AccordionItem>
}
<AccordionItem>
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
Remediation
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<label>Remediation instructions
<MarkdownEditor name="remediation" value={vulnerability.remediation || ""} onChange={onFormChange} />
</label>
<label>Remediation complexity
<Select name="remediation_complexity" value={vulnerability.remediation_complexity || ""} onChange={onFormChange} required>
{RemediationComplexity.map(complexity =>
<option key={complexity.id} value={complexity.id}>{complexity.name}</option>
)}
</Select>
</label>
<label>Remediation priority
<Select name="remediation_priority" value={vulnerability.remediation_priority || ""} onChange={onFormChange} required>
{RemediationPriority.map(priority =>
<option key={priority.id} value={priority.id}>{priority.name}</option>
)}
</Select>
</label>
</AccordionPanel>
</AccordionItem>
{
!vulnerability.is_template && <AccordionItem>
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
Relations
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<label>Project
<Select name="project_id" value={vulnerability.project_id || ""} onChange={onFormChange} required>
{projects && projects.map((project, index) =>
<option key={index} value={project.id}>{project.name}</option>
)}
</Select>
</label>
<label>Affected target
<Select name="target_id" value={vulnerability.target_id || ""} onChange={onFormChange}>
<option value="0">(none)</option>
{targets && targets.map((target, index) =>
<option key={index} value={target.id}>{target.name}</option>
)}
</Select>
</label>
</AccordionPanel>
</AccordionItem>
}
</Accordion>
<Primary type="submit">{isEditForm ? "Save" : "Add"}</Primary>
</form >
}
Example #18
Source File: index.js From UpStats with MIT License | 4 votes |
export default function Home({ status, systems, config }) {
console.log(status);
console.log(systems);
const [email, setEmail] = useState("");
const toast = useToast();
const handleSubmit = async (email) => {
try {
await http.post("/subs", { email: email });
toast({
title: "Success",
description: "Successfully Subscribed ",
status: "success",
duration: 9000,
isClosable: true,
});
} catch (ex) {
toast({
title: "Error",
description: "Submit Unsuccessful",
status: "error",
duration: 9000,
isClosable: true,
});
}
};
return (
<>
<Head>
<meta charSet="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<title>UP Stats</title>
<link rel="stylesheet" href="/main.css" />
</Head>
<main className="root">
<header className="top-0">
<nav>
<div className="content-center p-4">
{/* Nav Bar Logo */}
<img className="nav-brand" src="assets/img/logo.jpg" />
</div>
</nav>
</header>
<section>
<Center mt="5">
<Box bg="blue" w="90%" p={4} color="white" borderRadius="md">
{status.operational
? "All Systems Operational"
: `${status.outageCount} Systems Outage`}
</Box>
</Center>
<br />
<VStack>
{systems.map((system) => (
<Flex
id={system._id}
borderRadius="md"
boxShadow="lg"
w="90%"
p={3}
bg="white"
>
<Text pl={3}>{system.name}</Text>
<Spacer />
{system.status === "up" && (
<CheckCircleIcon mr={5} mt="1" color="green" />
)}
{system.status === "down" && (
<WarningIcon mr={5} mt="1" color="red" />
)}
</Flex>
))}
</VStack>
</section>
{config.mailing ? (
<VStack p={10} m={10} borderWidth={1} borderRadius="lg">
<h1 className="font-sans text-xl">Want to see Back in action?</h1>
<p className="font-sans">
Subscribe via Email and <br />
Get notified about the System Status
</p>
<Center>
<FormControl id="email" width="90%">
<FormLabel>Email address</FormLabel>
<Input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Box
width="8em"
mt="3"
height="3em"
border="1px"
color="white"
bg="blue"
borderRadius="lg"
p="3"
onClick={() => handleSubmit(email)}
>
<EmailIcon mr={3} />
Subscribe
</Box>
</FormControl>
</Center>
</VStack>
) : (
""
)}
<footer className="px-4 py-16 mx-auto max-w-7xl">
<nav className="grid grid-cols-2 gap-12 mb-12 md:grid-cols-3 lg:grid-cols-5">
<div>
<p className="mb-4 text-sm font-medium text-primary">
Handy Links
</p>
<a
className="flex mb-3 text-sm font-medium text-gray-700 transition md:mb-2 hover:text-primary"
href="https://github.com/ToolsHD/UPStats"
>
Opensource
</a>
<a
className="flex mb-3 text-sm font-medium text-gray-700 transition md:mb-2 hover:text-primary"
href="#"
>
Features
</a>
<a
className="flex mb-3 text-sm font-medium text-gray-700 transition md:mb-2 hover:text-primary"
href="#"
>
Pricing
</a>
</div>
</nav>
<div className="flex flex-col items-center justify-between md:flex-row">
<a href="/" className="mb-4 md:mb-0">
<img id="footer-img" src="assets/img/footer.jpg" />
<span className="sr-only">UpStats</span>
</a>
<p className="text-sm text-center text-gray-600 md:text-left">
© 2021 <a href="#">UP Stats</a>
</p>
</div>
</footer>
<div>
<button onClick="topFunction()" id="scroll-to-top">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M5 10l7-7m0 0l7 7m-7-7v18"
/>
</svg>
</button>
</div>
</main>
</>
);
}