fixed merge conflicts, added new nav

This commit is contained in:
Al Duncanson 2018-10-24 18:09:23 -04:00
commit 970762faa3
15 changed files with 476 additions and 193 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules/ node_modules/
.vscode/ .vscode/
.netlify

18
package-lock.json generated
View File

@ -6076,8 +6076,7 @@
}, },
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -6429,8 +6428,7 @@
}, },
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "bundled": true
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -6477,7 +6475,6 @@
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -6516,13 +6513,11 @@
}, },
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "bundled": true
"optional": true
} }
} }
}, },
@ -11871,6 +11866,11 @@
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
}, },
"react-quiz-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/react-quiz-component/-/react-quiz-component-0.2.0.tgz",
"integrity": "sha512-oWUos0A4NtYNBNoSqAbjjpZC9ndEuw5SebYRDhX2EUv4I41iqWWVNMbY2Pu7qT6I7MuELfWHrpV+5p0XwaChaQ=="
},
"react-router": { "react-router": {
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",

View File

@ -10,6 +10,7 @@
"google-maps-react": "^2.0.2", "google-maps-react": "^2.0.2",
"react": "^16.5.1", "react": "^16.5.1",
"react-dom": "^16.5.1", "react-dom": "^16.5.1",
"react-quiz-component": "0.2.0",
"react-router": "^4.3.1", "react-router": "^4.3.1",
"react-router-dom": "^4.3.1", "react-router-dom": "^4.3.1",
"react-scripts": "1.1.5" "react-scripts": "1.1.5"

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 KiB

View File

@ -2,12 +2,23 @@ body {
margin: 0; margin: 0;
} }
.report-google-map-container > div { /* #root > div > div {
width: 50% !important; overflow: scroll !important;
} */
div[class="ResponsiveDrawer-root-1"] {
overflow: scroll !important;
overflow-x: hidden !important;
} }
@media (min-width: 960px) { @media (min-width: 960px) {
.sighting-google-map-container > div { .sighting-google-map-container > div {
width: calc(100% - 241px) !important; width: calc(100% - 241px) !important;
} }
}
@media (min-width: 960px) {
.report-google-map-container > div {
width: 50% !important;
}
} }

View File

@ -20,7 +20,7 @@ import ListIcon from '@material-ui/icons/List';
import SlideshowIcon from '@material-ui/icons/Slideshow'; import SlideshowIcon from '@material-ui/icons/Slideshow';
import Home from '../pages/Home'; import Home from '../pages/Home';
import ViewMap from '../pages/ViewMap'; import ViewMap from '../pages/ViewMap';
import Quiz from '../pages/Quiz'; import QuizPage from '../pages/QuizPage';
import SightingList from '../pages/SightingList'; import SightingList from '../pages/SightingList';
import Report from '../pages/Report'; import Report from '../pages/Report';
@ -159,7 +159,7 @@ class ResponsiveDrawer extends React.Component {
{this.state.key === 'Report' && <Report />} {this.state.key === 'Report' && <Report />}
{this.state.key === 'Map' && <ViewMap />} {this.state.key === 'Map' && <ViewMap />}
{this.state.key === 'List' && <SightingList />} {this.state.key === 'List' && <SightingList />}
{this.state.key === 'Quiz' && <Quiz />} {this.state.key === 'Quiz' && <QuizPage />}
</div> </div>
); );
} }

160
src/components/QuizGame.js Normal file
View File

@ -0,0 +1,160 @@
import React, { Fragment } from 'react';
import Grid from '@material-ui/core/Grid';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import AppBar from '@material-ui/core/AppBar';
import Tabs from '@material-ui/core/Tabs';
import Tab from '@material-ui/core/Tab';
import Quiz from 'react-quiz-component';
/**
* Shuffles a given array.
* @param {*} array The array passed in.
*/
function shuffleArray(array) {
var j, x, i;
for (i = array.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = array[i];
array[i] = array[j];
array[j] = x;
}
return array;
}
function TabContainer(props) {
return (
<Typography component="div" variant='headline' align='center' style={{ padding: 8 }}>
{props.children}
</Typography>
);
}
TabContainer.propTypes = {
children: PropTypes.node.isRequired,
};
// Style for the tabs.
const styles = theme => ({
root: {
flexGrow: 1,
backgroundColor: theme.palette.background.paper,
marginTop: '64px',
overflow: 'scroll',
height: '95%',
},
});
class QuizGame extends React.Component {
// The state of the component.
state = {
value: 0,
};
// Handles tab changes.
handleChange = (event, value) => {
this.setState({ value });
};
// Object that contains the easy quiz material.
easyQuiz = {
"quizTitle": "Trail Cam Quiz: Easy",
"questions": shuffleArray([
{
"question": <Fragment>What animal is this?<br /><br /><img src="/quizimages/question1.jpg" alt=""></img></Fragment>,
"questionType": "text",
"answers": [
"Black bear",
"Common wombat",
"Raccoon",
"White-tailed deer"
],
"correctAnswer": "1"
},
{
"question": <Fragment>What animal is this?<br /><br /><img src="/quizimages/question2.jpg" alt=""></img></Fragment>,
"questionType": "text",
"answers": [
"American beaver",
"Muskrat",
"Porcupine",
"Woodchuck"
],
"correctAnswer": "3"
},
{
"question": <Fragment>What animal is this?<br /><br /><img src="/quizimages/question3.jpg" alt=""></img></Fragment>,
"questionType": "text",
"answers": [
"American badger",
"Raccoon",
"Striped skunk",
"Virginia opossum"
],
"correctAnswer": "2"
},
{
"question": <Fragment>What animal is this?<br /><br /><img src="/quizimages/question4.jpg" alt=""></img></Fragment>,
"questionType": "text",
"answers": [
"Eastern fox squirrel",
"Eastern gray squirrel",
"Red squirrel",
"Southern flying squirrel"
],
"correctAnswer": "3"
},
{
"question": <Fragment>What animal is this?<br /><br /><img src="/quizimages/question5.jpg" alt=""></img></Fragment>,
"questionType": "text",
"answers": [
"American Crow",
"Black Vulture",
"Turkey Vulture",
"Northern Raven"
],
"correctAnswer": "3"
},
])
};
// Renders the quiz component.
render() {
const { classes } = this.props;
const { value } = this.state;
return (
// Tabs
<div className={classes.root}>
<AppBar position="static">
<Tabs
value={value}
centered
fullWidth
onChange={this.handleChange}
>
<Tab label="Easy" />
<Tab label="Medium" />
<Tab label="Hard" />
</Tabs>
</AppBar>
{value === 0 && <TabContainer>
<Fragment>
<Grid container justify="center">
<Quiz quiz={this.easyQuiz} />
</Grid>
</Fragment>
</TabContainer>}
{value === 1 && <TabContainer>Medium Quiz</TabContainer>}
{value === 2 && <TabContainer>Hard Quiz</TabContainer>}
</div>
);
}
}
QuizGame.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(QuizGame);

View File

@ -1,4 +1,4 @@
import React, {Fragment} from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Grid from '@material-ui/core/Grid'; import Grid from '@material-ui/core/Grid';
import { withStyles } from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
@ -41,22 +41,15 @@ const styles = theme => ({
/** /**
* Function for formatting the * Function for formatting the
* date as a string that * year as a string that
* Material UI can use. We'll * Material UI can use.
* also store the date like
* this string in the database.
* @param {*} date, Date passed in. * @param {*} date, Date passed in.
*/ */
function formatDate(date) { function getYear(date) {
var d = new Date(date), var d = new Date(date),
month = '' + (d.getMonth() + 1), year = d.getFullYear();
day = '' + d.getDate(),
year = d.getFullYear();
if (month.length < 2) month = '0' + month; return year;
if (day.length < 2) day = '0' + day;
return [year, month, day].join('-');
} }
/** /**
@ -91,33 +84,117 @@ const sightingTypes = [
}, },
]; ];
/**
* Types of sightings. Label is what is
* viewed in the application, value is
* what is stored in the database.
*/
const monthTypes = [
{
value: '01',
label: 'January',
},
{
value: '02',
label: 'February',
},
{
value: '03',
label: 'March',
},
{
value: '04',
label: 'April',
},
{
value: '05',
label: 'May',
},
{
value: '06',
label: 'June',
},
{
value: '07',
label: 'July',
},
{
value: '08',
label: 'August',
},
{
value: '09',
label: 'September',
},
{
value: '10',
label: 'October',
},
{
value: '11',
label: 'November',
},
{
value: '12',
label: 'December',
},
];
/**
* Types of sightings. Label is what is
* viewed in the application, value is
* what is stored in the database.
*/
const timeTypes = [
{
value: 'unknown',
label: 'Unknown',
},
{
value: 'morning',
label: 'Morning',
},
{
value: 'midday',
label: 'Midday',
},
{
value: 'evening',
label: 'Evening',
},
{
value: 'night',
label: 'Night',
},
];
/** /**
* Levels of confidence. Label is what is * Levels of confidence. Label is what is
* viewed in the application, value is * viewed in the application, value is
* what is stored in the database. * what is stored in the database.
*/ */
const confidenceLevels = [ const confidenceLevels = [
{ {
value: '1', value: '1',
label: '1 - Strongly unconfident', label: '1 - Strongly disagree',
}, },
{ {
value: '2', value: '2',
label: '2 - Unconfident', label: '2 - Disagree',
}, },
{ {
value: '3', value: '3',
label: '3 - Somewhat confident', label: '3 - Neutral',
}, },
{ {
value: '4', value: '4',
label: '4 - Confident', label: '4 - Agree',
}, },
{ {
value: '5', value: '5',
label: '5 - Very confident', label: '5 - Strongly agree',
}, },
]; ];
/** /**
* The form component. * The form component.
@ -137,8 +214,9 @@ class ReportForm extends React.Component {
* State of form components. * State of form components.
*/ */
state = { state = {
date: formatDate(new Date()), month: '01',
time: '00:00', year: getYear(new Date()),
time: 'unknown',
type: 'visual', type: 'visual',
confidence: '1', confidence: '1',
desc: '', desc: '',
@ -160,13 +238,13 @@ class ReportForm extends React.Component {
* Get the coordinates * Get the coordinates
* *
*/ */
getCoordinates = (lat,lng) => { getCoordinates = (lat, lng) => {
let latitude = lat; let latitude = lat;
let longitude = lng; let longitude = lng;
this.setState({ this.setState({
lat: latitude, lat: latitude,
lng: longitude lng: longitude
}); });
} }
@ -182,7 +260,7 @@ class ReportForm extends React.Component {
const sighting = { const sighting = {
type: this.state.type, type: this.state.type,
confidence: this.state.confidence, confidence: this.state.confidence,
date: this.state.date, date: this.state.year + '-' + this.state.month,
time: this.state.time, time: this.state.time,
desc: this.state.desc, desc: this.state.desc,
lat: this.state.lat, lat: this.state.lat,
@ -190,8 +268,9 @@ class ReportForm extends React.Component {
} }
sightingsRef.push(sighting); sightingsRef.push(sighting);
this.setState({ this.setState({
date: formatDate(new Date()), year: getYear(new Date()),
time: '00:00', month: '01',
time: 'unknown',
type: 'visual', type: 'visual',
confidence: '1', confidence: '1',
desc: '', desc: '',
@ -199,7 +278,7 @@ class ReportForm extends React.Component {
lng: '' lng: ''
}); });
}; };
/** /**
* The render method for this component. * The render method for this component.
@ -211,129 +290,160 @@ class ReportForm extends React.Component {
* The actual form. * The actual form.
*/ */
return ( return (
<Fragment> <Fragment>
<form className={classes.container} autoComplete="off" onSubmit={this.handleSubmit}> <form className={classes.container} autoComplete="off" onSubmit={this.handleSubmit}>
<Grid container> <Grid container>
<Grid item xs={6}> <Grid item xs={12} md={6}>
<Grid container spacing={8}> <Grid container spacing={8}>
<Grid item xs={12}> <Grid item xs={12}>
<TextField <TextField
id="select-sighting-type" id="select-sighting-type"
select select
required required
name="sighting-type" name="sighting-type"
label="Select" label="Select"
className={classes.textField} className={classes.textField}
value={this.state.type} value={this.state.type}
onChange={this.handleChange('type')} onChange={this.handleChange('type')}
SelectProps={{ SelectProps={{
MenuProps: { MenuProps: {
className: classes.menu, className: classes.menu,
}, },
}} }}
helperText="Please select type of sighting" helperText="Please select type of sighting"
> >
{sightingTypes.map(option => ( {sightingTypes.map(option => (
<MenuItem key={option.value} value={option.value}> <MenuItem key={option.value} value={option.value}>
{option.label} {option.label}
</MenuItem> </MenuItem>
))} ))}
</TextField> </TextField>
</Grid>
<Grid item xs={12}>
<TextField
id="select-confidence"
select
required
name="sighting-confidence"
label="Select"
className={classes.textField}
value={this.state.confidence}
onChange={this.handleChange('confidence')}
SelectProps={{
MenuProps: {
className: classes.menu,
},
}}
helperText="Please select confidence in sighting"
>
{confidenceLevels.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12}>
<TextField
id="sighting-date"
required
label="Sighting date"
name="sighting-date"
type="date"
value={this.state.date}
className={classes.textField}
onChange={this.handleChange('date')}
InputLabelProps={{
shrink: true,
}}
/>
</Grid>
<Grid item xs={12}>
<TextField
id="sighting-time"
required
label="Sighting time"
name="sighting-time"
type="time"
margin="normal"
value={this.state.time}
className={classes.textField}
onChange={this.handleChange('time')}
InputLabelProps={{
shrink: true,
}}
/>
</Grid>
<Grid item xs={12}>
<TextField
id="sighting-description"
required
label="Description"
name="sighting-desc"
multiline
rows="5"
placeholder="Describe the sighting to the best of your ability."
value={this.state.desc}
className={classes.textField}
onChange={this.handleChange('desc')}
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 item xs={6}>
<GoogleMap onClick={this.getCoordinates}/>
</Grid>
</Grid> </Grid>
</form>
</Fragment> <Grid item xs={12}>
<TextField
id="select-confidence"
select
required
name="sighting-confidence"
label="Select"
className={classes.textField}
value={this.state.confidence}
onChange={this.handleChange('confidence')}
SelectProps={{
MenuProps: {
className: classes.menu,
},
}}
helperText="I am confident of my marten sighting"
>
{confidenceLevels.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12}>
<TextField
id="sighting-time"
select
required
label="Sighting time"
name="sighting-time"
className={classes.textField}
value={this.state.time}
onChange={this.handleChange('time')}
SelectProps={{
MenuProps: {
className: classes.menu,
},
}}
>
{timeTypes.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12}>
<TextField
id="sighting-month"
select
required
label="Sighting month"
name="sighting-month"
className={classes.textField}
value={this.state.month}
onChange={this.handleChange('month')}
SelectProps={{
MenuProps: {
className: classes.menu,
},
}}
>
{monthTypes.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12}>
<TextField
id="sighting-year"
required
label="Sighting year"
name="sighting-year"
value={this.state.year}
type="number"
className={classes.textField}
onChange={this.handleChange('year')}
InputLabelProps={{
shrink: true,
}}
/>
</Grid>
<Grid item xs={12}>
<TextField
id="sighting-description"
required
label="Description"
name="sighting-desc"
multiline
rows="5"
placeholder="Describe the sighting to the best of your ability."
value={this.state.desc}
className={classes.textField}
onChange={this.handleChange('desc')}
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 item xs={12} md={6}>
<GoogleMap onClick={this.getCoordinates} />
</Grid>
</Grid>
</form>
</Fragment>
); );
} }
} }
ReportForm.propTypes = { ReportForm.propTypes = {

View File

@ -1,5 +1,6 @@
import firebase from 'firebase/app'; import firebase from 'firebase/app';
import 'firebase/database'; import 'firebase/database';
import 'firebase/storage';
const config = { const config = {
apiKey: "AIzaSyAYf9AbeYwLY892NRiQfn0AMtG9xIFAJbo", apiKey: "AIzaSyAYf9AbeYwLY892NRiQfn0AMtG9xIFAJbo",

View File

@ -1,14 +0,0 @@
import React, { Component } from 'react';
import Typography from '@material-ui/core/Typography';
class Quiz extends Component {
render() {
return (
<Typography variant='display1' align='center' gutterBottom>
Quiz
</Typography>
);
}
}
export default Quiz;

13
src/pages/QuizPage.js Normal file
View File

@ -0,0 +1,13 @@
import React, { Component } from 'react';
import QuizGame from '../components/QuizGame';
class QuizPage extends Component {
render() {
return (
<QuizGame />
);
}
}
export default QuizPage;