Added contact form to application. Sends requests through EmailJS.
This commit is contained in:
		
							parent
							
								
									17410d3eec
								
							
						
					
					
						commit
						60e1e5e31f
					
				
							
								
								
									
										15
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										15
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -4246,6 +4246,21 @@
 | 
			
		||||
        "minimalistic-crypto-utils": "^1.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "emailjs-com": {
 | 
			
		||||
      "version": "2.2.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/emailjs-com/-/emailjs-com-2.2.4.tgz",
 | 
			
		||||
      "integrity": "sha512-Pm29HoSxEIKLv7p6rxOPpKFqLnf2JaHTl6coql59r8MNRNW49Mim65s7yoWAqQhZ+Mk4GFmQsiPSFXD6Gnm4BQ==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "promise-polyfill": "7.1.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "promise-polyfill": {
 | 
			
		||||
          "version": "7.1.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-7.1.0.tgz",
 | 
			
		||||
          "integrity": "sha512-P6NJ2wU/8fac44ENORsuqT8TiolKGB2u0fEClPtXezn7w5cmLIjM/7mhPlTebke2EPr6tmqZbXvnX0TxwykGrg=="
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "emoji-regex": {
 | 
			
		||||
      "version": "6.5.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz",
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@
 | 
			
		||||
    "@material-ui/icons": "^3.0.1",
 | 
			
		||||
    "ajv": "^6.0.0",
 | 
			
		||||
    "disqus-react": "^1.0.5",
 | 
			
		||||
    "emailjs-com": "^2.2.4",
 | 
			
		||||
    "firebase": "^5.5.2",
 | 
			
		||||
    "firebase-admin": "^6.1.0",
 | 
			
		||||
    "flamelink": "^0.19.6",
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,11 @@ body {
 | 
			
		||||
    height: 300px !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.contact-form {
 | 
			
		||||
    max-width: 100%;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (min-width: 960px) {
 | 
			
		||||
    .sighting-detail-google-map-container > div {
 | 
			
		||||
        width: calc(100% - 50% - 120px) !important;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										227
									
								
								src/components/ContactForm.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								src/components/ContactForm.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,227 @@
 | 
			
		||||
import React, { Fragment } from 'react';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import Grid from '@material-ui/core/Grid';
 | 
			
		||||
import emailjs from '../emailjs.js'
 | 
			
		||||
import { withStyles } from '@material-ui/core/styles';
 | 
			
		||||
import TextField from '@material-ui/core/TextField';
 | 
			
		||||
import CheckCircleIcon from '@material-ui/icons/CheckCircle';
 | 
			
		||||
import Snackbar from '@material-ui/core/Snackbar';
 | 
			
		||||
import IconButton from '@material-ui/core/IconButton';
 | 
			
		||||
import CloseIcon from '@material-ui/icons/Close';
 | 
			
		||||
import Button from '@material-ui/core/Button';
 | 
			
		||||
import { Typography } from '@material-ui/core';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Styles that the different
 | 
			
		||||
 * Material UI components pull
 | 
			
		||||
 * in. Mostly used for spacing.
 | 
			
		||||
 */
 | 
			
		||||
const styles = theme => ({
 | 
			
		||||
    container: {
 | 
			
		||||
        display: 'flex',
 | 
			
		||||
        flexWrap: 'wrap'
 | 
			
		||||
    },
 | 
			
		||||
    textField: {
 | 
			
		||||
        marginLeft: theme.spacing.unit,
 | 
			
		||||
        marginRight: theme.spacing.unit,
 | 
			
		||||
        marginTop: theme.spacing.unit,
 | 
			
		||||
        flexBasis: 280,
 | 
			
		||||
        width: '90%'
 | 
			
		||||
    },
 | 
			
		||||
    button: {
 | 
			
		||||
        marginLeft: theme.spacing.unit,
 | 
			
		||||
        marginRight: theme.spacing.unit,
 | 
			
		||||
        marginTop: theme.spacing.unit,
 | 
			
		||||
    },
 | 
			
		||||
    close: {
 | 
			
		||||
        padding: theme.spacing.unit / 2,
 | 
			
		||||
    },
 | 
			
		||||
    icon: {
 | 
			
		||||
        fontSize: 20,
 | 
			
		||||
        marginRight: theme.spacing.unit,
 | 
			
		||||
    },
 | 
			
		||||
    message: {
 | 
			
		||||
        display: 'flex',
 | 
			
		||||
        alignItems: 'center',
 | 
			
		||||
    },
 | 
			
		||||
    menu: {
 | 
			
		||||
        width: 200,
 | 
			
		||||
    },
 | 
			
		||||
    paper: {
 | 
			
		||||
        position: 'absolute',
 | 
			
		||||
        width: theme.spacing.unit * 50,
 | 
			
		||||
        backgroundColor: theme.palette.background.paper,
 | 
			
		||||
        boxShadow: theme.shadows[5],
 | 
			
		||||
        padding: theme.spacing.unit * 4,
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The form component.
 | 
			
		||||
 */
 | 
			
		||||
class ContactForm extends React.Component {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * State of form components.
 | 
			
		||||
     */
 | 
			
		||||
    state = {
 | 
			
		||||
        name: "",
 | 
			
		||||
        email: "",
 | 
			
		||||
        comments: "",
 | 
			
		||||
        open: false
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles state change in form
 | 
			
		||||
     * components.
 | 
			
		||||
     */
 | 
			
		||||
    handleChange = name => event => {
 | 
			
		||||
        this.setState({
 | 
			
		||||
            [name]: event.target.value,
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handles closing the toast.
 | 
			
		||||
     */
 | 
			
		||||
    handleClose = (event, reason) => {
 | 
			
		||||
        if (reason === 'clickaway') {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.setState({ open: false });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Event listener for form.
 | 
			
		||||
     * When the form is submitted,
 | 
			
		||||
     * this function passes the
 | 
			
		||||
     * data along to EmailJS.
 | 
			
		||||
     */
 | 
			
		||||
    handleSubmit = e => {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
 | 
			
		||||
        const templateParams = {
 | 
			
		||||
            from_name: this.state.name,
 | 
			
		||||
            from_email: this.state.email,
 | 
			
		||||
            message_html: this.state.comments
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        emailjs.send('default_service', 'template_XaKOJGSf', templateParams);
 | 
			
		||||
 | 
			
		||||
        this.setState({
 | 
			
		||||
            name: "",
 | 
			
		||||
            email: "",
 | 
			
		||||
            comments: "",
 | 
			
		||||
            open: true
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The render method for this component.
 | 
			
		||||
     */
 | 
			
		||||
    render() {
 | 
			
		||||
        const { classes } = this.props;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * The actual form.
 | 
			
		||||
         */
 | 
			
		||||
        return (
 | 
			
		||||
            <Fragment>
 | 
			
		||||
                <Typography variant="headline" align="center">
 | 
			
		||||
                {<br/>}
 | 
			
		||||
                Send us an email!
 | 
			
		||||
 | 
			
		||||
                <form className={classes.container} autoComplete="off" onSubmit={this.handleSubmit}>
 | 
			
		||||
                    <Grid container className="contact-form">
 | 
			
		||||
                        <Grid item xs={12}>
 | 
			
		||||
                            <Grid container spacing={8}>
 | 
			
		||||
                                <Grid item xs={12}>
 | 
			
		||||
                                    <TextField
 | 
			
		||||
                                        id="name"
 | 
			
		||||
                                        required
 | 
			
		||||
                                        label="Name"
 | 
			
		||||
                                        name="message-name"
 | 
			
		||||
                                        placeholder="John Doe"
 | 
			
		||||
                                        value={this.state.name}
 | 
			
		||||
                                        className={classes.textField}
 | 
			
		||||
                                        onChange={this.handleChange('name')}
 | 
			
		||||
                                        margin="normal"
 | 
			
		||||
                                        variant="outlined"
 | 
			
		||||
                                    />
 | 
			
		||||
                                    <TextField
 | 
			
		||||
                                        id="email"
 | 
			
		||||
                                        required
 | 
			
		||||
                                        label="Email"
 | 
			
		||||
                                        name="message-email"
 | 
			
		||||
                                        type="email"
 | 
			
		||||
                                        autoComplete="email"
 | 
			
		||||
                                        placeholder="example@mail.com"
 | 
			
		||||
                                        value={this.state.email}
 | 
			
		||||
                                        className={classes.textField}
 | 
			
		||||
                                        onChange={this.handleChange('email')}
 | 
			
		||||
                                        margin="normal"
 | 
			
		||||
                                        variant="outlined"
 | 
			
		||||
                                    />
 | 
			
		||||
                                    <TextField
 | 
			
		||||
                                        id="comments"
 | 
			
		||||
                                        required
 | 
			
		||||
                                        label="Comments"
 | 
			
		||||
                                        name="message-comments"
 | 
			
		||||
                                        multiline
 | 
			
		||||
                                        rows="5"
 | 
			
		||||
                                        placeholder="The message you would like to send us."
 | 
			
		||||
                                        value={this.state.comments}
 | 
			
		||||
                                        className={classes.textField}
 | 
			
		||||
                                        onChange={this.handleChange('comments')}
 | 
			
		||||
                                        margin="normal"
 | 
			
		||||
                                        variant="outlined"
 | 
			
		||||
                                        InputLabelProps={{
 | 
			
		||||
                                            shrink: true,
 | 
			
		||||
                                        }}
 | 
			
		||||
                                    />
 | 
			
		||||
                                </Grid>
 | 
			
		||||
                                <Grid item xs={12}>
 | 
			
		||||
                                    <Button variant="contained" type="submit" color="primary" className={classes.button}>
 | 
			
		||||
                                        Submit
 | 
			
		||||
                                    </Button>
 | 
			
		||||
                                </Grid>
 | 
			
		||||
                            </Grid>
 | 
			
		||||
                        </Grid>
 | 
			
		||||
                    </Grid>
 | 
			
		||||
                </form>
 | 
			
		||||
                </Typography>
 | 
			
		||||
                <Snackbar
 | 
			
		||||
                    anchorOrigin={{
 | 
			
		||||
                        vertical: 'bottom',
 | 
			
		||||
                        horizontal: 'left',
 | 
			
		||||
                    }}
 | 
			
		||||
                    open={this.state.open}
 | 
			
		||||
                    autoHideDuration={6000}
 | 
			
		||||
                    onClose={this.handleClose}
 | 
			
		||||
                    ContentProps={{
 | 
			
		||||
                        'aria-describedby': 'message-id',
 | 
			
		||||
                    }}
 | 
			
		||||
                    message={<span id="message-id" className={classes.message}><CheckCircleIcon className={classes.icon} />Message sent.</span>}
 | 
			
		||||
                    action={[
 | 
			
		||||
                        <IconButton
 | 
			
		||||
                            key="close"
 | 
			
		||||
                            aria-label="Close"
 | 
			
		||||
                            color="inherit"
 | 
			
		||||
                            className={classes.close}
 | 
			
		||||
                            onClick={this.handleClose}
 | 
			
		||||
                        >
 | 
			
		||||
                            <CloseIcon />
 | 
			
		||||
                        </IconButton>,
 | 
			
		||||
                    ]}
 | 
			
		||||
                />
 | 
			
		||||
            </Fragment>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ContactForm.propTypes = {
 | 
			
		||||
    classes: PropTypes.object.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default withStyles(styles)(ContactForm);
 | 
			
		||||
@ -14,6 +14,7 @@ import Hidden from '@material-ui/core/Hidden';
 | 
			
		||||
import Divider from '@material-ui/core/Divider';
 | 
			
		||||
import MenuIcon from '@material-ui/icons/Menu';
 | 
			
		||||
import HomeIcon from '@material-ui/icons/Home';
 | 
			
		||||
import EmailIcon from '@material-ui/icons/Email';
 | 
			
		||||
import AssignmentIcon from '@material-ui/icons/Assignment';
 | 
			
		||||
import MapIcon from '@material-ui/icons/Map';
 | 
			
		||||
import InfoIcon from '@material-ui/icons/Info';
 | 
			
		||||
@ -23,6 +24,7 @@ import Home from '../pages/Home';
 | 
			
		||||
import ViewMap from '../pages/ViewMap';
 | 
			
		||||
import Info from '../pages/Info';
 | 
			
		||||
import Quiz from '../pages/QuizPage';
 | 
			
		||||
import Contact from '../pages/Contact';
 | 
			
		||||
import SightingList from '../pages/SightingList';
 | 
			
		||||
import Report from '../pages/Report';
 | 
			
		||||
import CssBaseline from '@material-ui/core/CssBaseline';
 | 
			
		||||
@ -112,10 +114,6 @@ class ResponsiveDrawer extends React.Component {
 | 
			
		||||
                        <ListItemIcon><ListIcon /></ListItemIcon>
 | 
			
		||||
                        <ListItemText primary='List' />
 | 
			
		||||
                    </ListItem>
 | 
			
		||||
                    <ListItem button key='About' onClick={() => this.nav('About')}>
 | 
			
		||||
                        <ListItemIcon><InfoIcon /></ListItemIcon>
 | 
			
		||||
                        <ListItemText primary='About' />
 | 
			
		||||
                    </ListItem>
 | 
			
		||||
                    <ListItem button onClick={this.handleClick}>
 | 
			
		||||
                        <ListItemIcon>
 | 
			
		||||
                            <SlideshowIcon />
 | 
			
		||||
@ -136,6 +134,14 @@ class ResponsiveDrawer extends React.Component {
 | 
			
		||||
                            </ListItem>
 | 
			
		||||
                        </List>
 | 
			
		||||
                    </Collapse>
 | 
			
		||||
                    <ListItem button key='Contact' onClick={() => this.nav('Contact')}>
 | 
			
		||||
                        <ListItemIcon><EmailIcon /></ListItemIcon>
 | 
			
		||||
                        <ListItemText primary='Contact' />
 | 
			
		||||
                    </ListItem>
 | 
			
		||||
                    <ListItem button key='About' onClick={() => this.nav('About')}>
 | 
			
		||||
                        <ListItemIcon><InfoIcon /></ListItemIcon>
 | 
			
		||||
                        <ListItemText primary='About' />
 | 
			
		||||
                    </ListItem>
 | 
			
		||||
                </List>
 | 
			
		||||
                <Divider />
 | 
			
		||||
            </div>
 | 
			
		||||
@ -196,6 +202,7 @@ class ResponsiveDrawer extends React.Component {
 | 
			
		||||
                    {this.state.key === 'Map' && <ViewMap />}
 | 
			
		||||
                    {this.state.key === 'List' && <SightingList />}
 | 
			
		||||
                    {this.state.key === 'About' && <Info />}
 | 
			
		||||
                    {this.state.key === 'Contact' && <Contact />}
 | 
			
		||||
                    {this.state.key === 'Easy-Quiz' && <Quiz difficulty='Easy'/>}
 | 
			
		||||
                    {this.state.key === 'Medium-Quiz' && <Quiz difficulty='Medium'/>}
 | 
			
		||||
                    {this.state.key === 'Hard-Quiz' && <Quiz difficulty='Hard'/>}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								src/emailjs.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/emailjs.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
import * as emailjs from 'emailjs-com'
 | 
			
		||||
 | 
			
		||||
emailjs.init("user_4d5R86dmu6vgeJP4euxSA");
 | 
			
		||||
 | 
			
		||||
export default emailjs;
 | 
			
		||||
							
								
								
									
										14
									
								
								src/pages/Contact.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/pages/Contact.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
import React, { Component } from 'react';
 | 
			
		||||
import ContactForm from '../components/ContactForm.js'
 | 
			
		||||
 | 
			
		||||
class Contact extends Component {
 | 
			
		||||
    componentDidMount() {
 | 
			
		||||
        document.title = 'Marten Tracker | Contact';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        return <ContactForm />;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default Contact;
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user