diff --git a/components/ContactModal/index.js b/components/ContactModal/index.js new file mode 100644 index 0000000..327c897 --- /dev/null +++ b/components/ContactModal/index.js @@ -0,0 +1,207 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import { + Container, + Typography, + Button, + Grid, + makeStyles, + Dialog, +} from '@material-ui/core'; +import MailIcon from '@material-ui/icons/Mail'; + +import { Formik, Form, Field } from 'formik'; +import { TextField } from 'formik-material-ui'; + +import SnackAlert from '../shared/SnackAlert'; +import emailValidator from '../../utils/emailValidator'; +import api from '../../utils/api'; + +const useStyles = makeStyles((theme) => ({ + paper: { + backgroundColor: theme.palette.background.paper, + boxShadow: theme.shadows[5], + padding: theme.spacing(2, 4, 3), + borderRadius: '10px', + }, + mailIcon: { + color: theme.palette.secondary.main, + fontSize: '4rem', + justifyContent: 'center', + }, + aside: { + backgroundColor: theme.palette.primary.main, + height: '100%', + }, + title: { + marginBottom: theme.spacing(2), + }, +})); + +export default function Contact({ open, setOpen }) { + const classes = useStyles(); + const [successOpen, setSuccessOpen] = useState(false); + const [errorOpen, setErrorOpen] = useState(false); + + const handleClose = () => { + setOpen(false); + }; + + const initialValues = { + full_name: '', + email: '', + message: '', + }; + + const handleValidate = (values) => { + const errors = {}; + if (!values.full_name) { + errors.full_name = 'Required'; + } + + if (!values.email) { + errors.email = 'Required'; + } else if (emailValidator(values.email)) { + errors.email = 'Invalid Email Address'; + } + + if (!values.message) { + errors.message = 'Required'; + } + return errors; + }; + + const handleSubmit = async (values) => { + api.post('/contact', values) + .then(() => setSuccessOpen(true)) + .catch(() => setErrorOpen(true)); + }; + + const handleSnackClose = (_, reason) => { + if (reason === 'clickaway') { + return; + } + + setSuccessOpen(false); + setErrorOpen(false); + }; + + return ( +
+ + + +
+ + + + + + If you’re having any issues with our service feel + free to contact us and we’ll get back to you as soon as possible + + + + + + + + Contact Us + + + handleValidate(values)} + onSubmit={(values, { setSubmitting }) => handleSubmit(values, setSubmitting)} + > + {({ + submitForm, isSubmitting, values, + }) => ( +
+ + + + + + + + + +
+ )} +
+ +
+ +
+
+
+
+
+ ); +} + +Contact.propTypes = { + open: PropTypes.bool.isRequired, + setOpen: PropTypes.func.isRequired, +}; diff --git a/components/Dashboard/Card.js b/components/Dashboard/Card.js index 12fcb24..5104b7f 100644 --- a/components/Dashboard/Card.js +++ b/components/Dashboard/Card.js @@ -5,8 +5,9 @@ import { makeStyles, Divider, Typography, - Link, + // Link, } from '@material-ui/core'; +import Link from 'next/link'; const useStyles = makeStyles((theme) => ({ title: { @@ -37,17 +38,18 @@ function Card({ bridge, index }) { return ( - - + + {bridge.title} - - + + + @@ -92,13 +94,18 @@ function Card({ bridge, index }) { {bridge.eventId ? ( - - + + + View Events - - + + ) : ( - + View Events )} @@ -115,7 +122,7 @@ export default Card; Card.propTypes = { bridge: PropTypes.shape({ - id: PropTypes.number.isRequired, + slug: PropTypes.string.isRequired, title: PropTypes.string.isRequired, updatedAt: PropTypes.string.isRequired, eventCount: PropTypes.number.isRequired, diff --git a/components/Editor/ActionsDialog/index.js b/components/Editor/ActionsDialog/index.js index 83a981c..678a007 100644 --- a/components/Editor/ActionsDialog/index.js +++ b/components/Editor/ActionsDialog/index.js @@ -26,7 +26,7 @@ const useStyles = makeStyles({ }); function ActionsDialog({ - active, open, onClose, bridgeId, + active, open, onClose, bridgeSlug, }) { const [errorOpen, setErrorOpen] = useState(false); const [successOpen, setSuccessOpen] = useState(false); @@ -35,7 +35,7 @@ function ActionsDialog({ const handleAbort = () => { api.patch('/events/abort', { - bridge_id: bridgeId, + bridge_slug: bridgeSlug, }) .then((res) => { if (res.status === 200) { @@ -51,8 +51,8 @@ function ActionsDialog({ }; const handleActivate = async () => { - await api.patch(`/bridges/${bridgeId}/${active ? 'deactivate' : 'activate'}`).then(() => { - router.push(`/bridge/${bridgeId}`); + await api.patch(`/bridges/${bridgeSlug}/${active ? 'deactivate' : 'activate'}`).then(() => { + router.push(`/bridge/${bridgeSlug}`); setSuccessOpen(true); setTimeout(() => { setSuccessOpen(false); @@ -66,7 +66,7 @@ function ActionsDialog({ }; const handleDelete = () => { - api.delete(`/bridges/${bridgeId}`).then(() => { + api.delete(`/bridges/${bridgeSlug}`).then(() => { router.push('/dashboard'); }).catch(() => { setErrorOpen(true); @@ -136,7 +136,7 @@ ActionsDialog.propTypes = { active: PropTypes.bool.isRequired, onClose: PropTypes.func.isRequired, open: PropTypes.bool.isRequired, - bridgeId: PropTypes.number.isRequired, + bridgeSlug: PropTypes.string.isRequired, }; export default ActionsDialog; diff --git a/components/Editor/index.js b/components/Editor/index.js index 69719f4..1d6080d 100644 --- a/components/Editor/index.js +++ b/components/Editor/index.js @@ -49,7 +49,7 @@ function Editor({ bridge, isEditView }) { const { active, - id, + slug, outboundUrl, httpMethod, headers, @@ -140,9 +140,9 @@ function Editor({ bridge, isEditView }) { const handleSubmit = async (values, setSubmitting) => { if (validatePayloads(values.payloadCode, values.testPayloadCode)) { // POST if new bridge, otherwise PATCH - if (id) { + if (slug) { await api - .patch(`/bridges/${id}`, generatePayload(values)) + .patch(`/bridges/${slug}`, generatePayload(values)) .then(() => setOpen(true)) .catch(() => setErrorOpen(true)); } else { @@ -153,7 +153,7 @@ function Editor({ bridge, isEditView }) { // TODO: Should timeout so user gets a chance to read the snack // but is 200ms the time we want? setTimeout(() => { - router.push(`/bridge/${res.data.id}`); + router.push(`/bridge/${res.data.slug}`); }, 200); }) .catch(() => setErrorOpen(true)); @@ -175,7 +175,7 @@ function Editor({ bridge, isEditView }) { return ( <> - + @@ -209,7 +209,7 @@ function Editor({ bridge, isEditView }) { active={active} open={actionsDialogOpen} onClose={() => setActionsDialogOpen(false)} - bridgeId={id} + bridgeSlug={slug} /> - - - Join the developers that are integrating API's around the world. - - - - - - - - Bridge Incompatible API's - - - - - BridgeAPI is a serverless integration platform that - - - empowers users to connect apps through event-driven workflows - - - - - - Join the developers that are integrating API's around the world. - - - - - -