fix merge conflicts
This commit is contained in:
		
						commit
						d926c107c0
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,2 +1,3 @@
 | 
				
			|||||||
node_modules/
 | 
					node_modules/
 | 
				
			||||||
.vscode/
 | 
					.vscode/
 | 
				
			||||||
 | 
					.netlify
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										91
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										91
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -392,6 +392,30 @@
 | 
				
			|||||||
        "warning": "^4.0.1"
 | 
					        "warning": "^4.0.1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "@material-ui/icons": {
 | 
				
			||||||
 | 
					      "version": "3.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-3.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-1kNcxYiIT1x8iDPEAlgmKrfRTIV8UyK6fLVcZ9kMHIKGWft9I451V5mvSrbCjbf7MX1TbLWzZjph0aVCRf9MqQ==",
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "@babel/runtime": "7.0.0",
 | 
				
			||||||
 | 
					        "recompose": "^0.29.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "recompose": {
 | 
				
			||||||
 | 
					          "version": "0.29.0",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.29.0.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-J/qLXNU4W+AeHCDR70ajW8eMd1uroqZaECTj6qqDLPMILz3y0EzpYlvrnxKB9DnqcngWrtGwjXY9JeXaW9kS1A==",
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "@babel/runtime": "^7.0.0",
 | 
				
			||||||
 | 
					            "change-emitter": "^0.1.2",
 | 
				
			||||||
 | 
					            "fbjs": "^0.8.1",
 | 
				
			||||||
 | 
					            "hoist-non-react-statics": "^2.3.1",
 | 
				
			||||||
 | 
					            "react-lifecycles-compat": "^3.0.2",
 | 
				
			||||||
 | 
					            "symbol-observable": "^1.0.4"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "@mrmlnc/readdir-enhanced": {
 | 
					    "@mrmlnc/readdir-enhanced": {
 | 
				
			||||||
      "version": "2.2.1",
 | 
					      "version": "2.2.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
 | 
				
			||||||
@ -3027,6 +3051,16 @@
 | 
				
			|||||||
        "sha.js": "^2.4.8"
 | 
					        "sha.js": "^2.4.8"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "create-react-class": {
 | 
				
			||||||
 | 
					      "version": "15.6.3",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==",
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "fbjs": "^0.8.9",
 | 
				
			||||||
 | 
					        "loose-envify": "^1.3.1",
 | 
				
			||||||
 | 
					        "object-assign": "^4.1.1"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "cross-spawn": {
 | 
					    "cross-spawn": {
 | 
				
			||||||
      "version": "5.1.0",
 | 
					      "version": "5.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
 | 
				
			||||||
@ -3543,6 +3577,40 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "disqus-react": {
 | 
				
			||||||
 | 
					      "version": "1.0.5",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/disqus-react/-/disqus-react-1.0.5.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-go6hhr0kHF4qbf66tRNeUqLZHRE=",
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "react": "^15.6.1",
 | 
				
			||||||
 | 
					        "react-dom": "^15.6.1"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "react": {
 | 
				
			||||||
 | 
					          "version": "15.6.2",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/react/-/react-15.6.2.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-26BDSrQ5z+gvEI8PURZjkIF5qnI=",
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "create-react-class": "^15.6.0",
 | 
				
			||||||
 | 
					            "fbjs": "^0.8.9",
 | 
				
			||||||
 | 
					            "loose-envify": "^1.1.0",
 | 
				
			||||||
 | 
					            "object-assign": "^4.1.0",
 | 
				
			||||||
 | 
					            "prop-types": "^15.5.10"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "react-dom": {
 | 
				
			||||||
 | 
					          "version": "15.6.2",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.2.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-Qc+t9pO3V/rycIRDodH9WgK+9zA=",
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "fbjs": "^0.8.9",
 | 
				
			||||||
 | 
					            "loose-envify": "^1.1.0",
 | 
				
			||||||
 | 
					            "object-assign": "^4.1.0",
 | 
				
			||||||
 | 
					            "prop-types": "^15.5.10"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "dns-equal": {
 | 
					    "dns-equal": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
 | 
				
			||||||
@ -6076,8 +6144,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 +6496,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 +6543,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 +6581,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
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -9529,6 +9592,11 @@
 | 
				
			|||||||
      "integrity": "sha512-9DITV2YEMcw7XojdfvGl3gDD8J9QjZTJ7ZOUuSAkP+F3T6rDbzMJuPktxptsdHYEvZcmXrCD3LMOhdSAEq6zKA==",
 | 
					      "integrity": "sha512-9DITV2YEMcw7XojdfvGl3gDD8J9QjZTJ7ZOUuSAkP+F3T6rDbzMJuPktxptsdHYEvZcmXrCD3LMOhdSAEq6zKA==",
 | 
				
			||||||
      "optional": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "moment": {
 | 
				
			||||||
 | 
					      "version": "2.22.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "ms": {
 | 
					    "ms": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
 | 
				
			||||||
@ -11871,6 +11939,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",
 | 
				
			||||||
 | 
				
			|||||||
@ -4,12 +4,16 @@
 | 
				
			|||||||
  "private": true,
 | 
					  "private": true,
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@material-ui/core": "^3.1.0",
 | 
					    "@material-ui/core": "^3.1.0",
 | 
				
			||||||
 | 
					    "@material-ui/icons": "^3.0.1",
 | 
				
			||||||
 | 
					    "disqus-react": "^1.0.5",
 | 
				
			||||||
    "firebase": "^5.5.2",
 | 
					    "firebase": "^5.5.2",
 | 
				
			||||||
    "firebase-admin": "^6.0.0",
 | 
					    "firebase-admin": "^6.0.0",
 | 
				
			||||||
    "flamelink": "^0.19.2",
 | 
					    "flamelink": "^0.19.2",
 | 
				
			||||||
    "google-maps-react": "^2.0.2",
 | 
					    "google-maps-react": "^2.0.2",
 | 
				
			||||||
 | 
					    "moment": "^2.22.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"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,17 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
<html lang="en">
 | 
					<html lang="en">
 | 
				
			||||||
  <head>
 | 
					  <head>
 | 
				
			||||||
 | 
					    <!-- Global site tag (gtag.js) - Google Analytics -->
 | 
				
			||||||
 | 
					    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-128154616-1"></script>
 | 
				
			||||||
 | 
					    <script>
 | 
				
			||||||
 | 
					    window.dataLayer = window.dataLayer || [];
 | 
				
			||||||
 | 
					    function gtag(){dataLayer.push(arguments);}
 | 
				
			||||||
 | 
					    gtag('js', new Date());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gtag('config', 'UA-128154616-1');
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <meta charset="utf-8">
 | 
					    <meta charset="utf-8">
 | 
				
			||||||
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
					    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
				
			||||||
    <meta name="theme-color" content="#000000">
 | 
					    <meta name="theme-color" content="#000000">
 | 
				
			||||||
@ -30,15 +41,16 @@
 | 
				
			|||||||
      You need to enable JavaScript to run this app.
 | 
					      You need to enable JavaScript to run this app.
 | 
				
			||||||
    </noscript>
 | 
					    </noscript>
 | 
				
			||||||
    <div id="root"></div>
 | 
					    <div id="root"></div>
 | 
				
			||||||
    <!--
 | 
					    <!-- Hotjar Tracking Code for https://marten-application.netlify.com/ -->
 | 
				
			||||||
      This HTML file is a template.
 | 
					    <script>
 | 
				
			||||||
      If you open it directly in the browser, you will see an empty page.
 | 
					        (function(h,o,t,j,a,r){
 | 
				
			||||||
 | 
					            h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
 | 
				
			||||||
      You can add webfonts, meta tags, or analytics to this file.
 | 
					            h._hjSettings={hjid:1066756,hjsv:6};
 | 
				
			||||||
      The build step will place the bundled scripts into the <body> tag.
 | 
					            a=o.getElementsByTagName('head')[0];
 | 
				
			||||||
 | 
					            r=o.createElement('script');r.async=1;
 | 
				
			||||||
      To begin the development, run `npm start` or `yarn start`.
 | 
					            r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
 | 
				
			||||||
      To create a production bundle, use `npm run build` or `yarn build`.
 | 
					            a.appendChild(r);
 | 
				
			||||||
    -->
 | 
					        })(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
  </body>
 | 
					  </body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								public/quizimages/question1.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/quizimages/question1.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 608 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/quizimages/question2.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/quizimages/question2.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 152 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/quizimages/question3.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/quizimages/question3.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 252 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/quizimages/question4.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/quizimages/question4.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 434 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								public/quizimages/question5.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/quizimages/question5.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 782 KiB  | 
							
								
								
									
										48
									
								
								src/App.css
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								src/App.css
									
									
									
									
									
								
							@ -2,11 +2,49 @@ body {
 | 
				
			|||||||
    margin: 0;
 | 
					    margin: 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.report-google-map-container > div {
 | 
					@media (min-width: 600px) {
 | 
				
			||||||
    height: 92% !important;
 | 
					    .sighting-google-map-container > div {
 | 
				
			||||||
    width: 50% !important;
 | 
					        width: calc(100% - 240px) !important;
 | 
				
			||||||
 | 
					        height: calc(100% - 64px) !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.sighting-google-map-container > div {
 | 
					@media (min-width: 960px) {
 | 
				
			||||||
    height: 92% !important;
 | 
					    .report-google-map-container > div {
 | 
				
			||||||
 | 
					        width: calc(100% - 50% - 120px) !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#disqus_thread {
 | 
				
			||||||
 | 
					    width: 89% !important;
 | 
				
			||||||
 | 
					    margin: 0 auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.sighting-list {
 | 
				
			||||||
 | 
					    height: calc(50vh - 64px);
 | 
				
			||||||
 | 
					    overflow-y: scroll;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media (min-width: 960px) {
 | 
				
			||||||
 | 
					    .sighting-list {
 | 
				
			||||||
 | 
					        height: calc(100vh - 64px);
 | 
				
			||||||
 | 
					        overflow-y: scroll;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.sighting-details-content {
 | 
				
			||||||
 | 
					    width: 89%;
 | 
				
			||||||
 | 
					    margin: 330px auto 0 auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.sighting-detail-google-map-container > div {
 | 
				
			||||||
 | 
					    width: 100% !important;
 | 
				
			||||||
 | 
					    height: 300px !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media (min-width: 960px) {
 | 
				
			||||||
 | 
					    .sighting-detail-google-map-container > div {
 | 
				
			||||||
 | 
					        width: calc(100% - 50% - 120px) !important;
 | 
				
			||||||
 | 
					        height: 300px !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -2,7 +2,6 @@ import { Component } from 'react';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Flamelink extends Component {
 | 
					class Flamelink extends Component {
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return(null);
 | 
					        return(null);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,75 +1,209 @@
 | 
				
			|||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import { withStyles } from '@material-ui/core/styles';
 | 
					import { withStyles } from '@material-ui/core/styles';
 | 
				
			||||||
 | 
					import Drawer from '@material-ui/core/Drawer';
 | 
				
			||||||
import AppBar from '@material-ui/core/AppBar';
 | 
					import AppBar from '@material-ui/core/AppBar';
 | 
				
			||||||
import Tabs from '@material-ui/core/Tabs';
 | 
					import Toolbar from '@material-ui/core/Toolbar';
 | 
				
			||||||
import Tab from '@material-ui/core/Tab';
 | 
					import List from '@material-ui/core/List';
 | 
				
			||||||
 | 
					import ListItem from '@material-ui/core/ListItem';
 | 
				
			||||||
 | 
					import ListItemIcon from '@material-ui/core/ListItemIcon';
 | 
				
			||||||
 | 
					import ListItemText from '@material-ui/core/ListItemText';
 | 
				
			||||||
import Typography from '@material-ui/core/Typography';
 | 
					import Typography from '@material-ui/core/Typography';
 | 
				
			||||||
 | 
					import IconButton from '@material-ui/core/IconButton';
 | 
				
			||||||
 | 
					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 AssignmentIcon from '@material-ui/icons/Assignment';
 | 
				
			||||||
 | 
					import MapIcon from '@material-ui/icons/Map';
 | 
				
			||||||
 | 
					import ListIcon from '@material-ui/icons/List';
 | 
				
			||||||
 | 
					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 Quiz from '../pages/QuizPage';
 | 
				
			||||||
import SightingList from '../pages/SightingList';
 | 
					import SightingList from '../pages/SightingList';
 | 
				
			||||||
import Report from '../pages/Report';
 | 
					import Report from '../pages/Report';
 | 
				
			||||||
import Info from '../pages/Info';
 | 
					import CssBaseline from '@material-ui/core/CssBaseline';
 | 
				
			||||||
 | 
					import ExpandLess from '@material-ui/icons/ExpandLess';
 | 
				
			||||||
 | 
					import ExpandMore from '@material-ui/icons/ExpandMore';
 | 
				
			||||||
 | 
					import Collapse from '@material-ui/core/Collapse';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function TabContainer(props) {
 | 
					const drawerWidth = 240;
 | 
				
			||||||
    return (
 | 
					 | 
				
			||||||
        <Typography component="div" style={{ padding: 8 * 3 }}>
 | 
					 | 
				
			||||||
            {props.children}
 | 
					 | 
				
			||||||
        </Typography>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
TabContainer.propTypes = {
 | 
					 | 
				
			||||||
    children: PropTypes.node.isRequired,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const styles = theme => ({
 | 
					const styles = theme => ({
 | 
				
			||||||
    root: {
 | 
					    root: {
 | 
				
			||||||
 | 
					        display: 'flex',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    drawer: {
 | 
				
			||||||
 | 
					        [theme.breakpoints.up('sm')]: {
 | 
				
			||||||
 | 
					            width: drawerWidth,
 | 
				
			||||||
 | 
					            flexShrink: 0,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    nested: {
 | 
				
			||||||
 | 
					        paddingLeft: theme.spacing.unit * 4,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    appBar: {
 | 
				
			||||||
 | 
					        marginLeft: drawerWidth,
 | 
				
			||||||
 | 
					        [theme.breakpoints.up('sm')]: {
 | 
				
			||||||
 | 
					            width: `calc(100% - ${drawerWidth}px)`,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    menuButton: {
 | 
				
			||||||
 | 
					        marginRight: 20,
 | 
				
			||||||
 | 
					        [theme.breakpoints.up('sm')]: {
 | 
				
			||||||
 | 
					            display: 'none',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    toolbar: theme.mixins.toolbar,
 | 
				
			||||||
 | 
					    drawerPaper: {
 | 
				
			||||||
 | 
					        width: drawerWidth,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    content: {
 | 
				
			||||||
        flexGrow: 1,
 | 
					        flexGrow: 1,
 | 
				
			||||||
        backgroundColor: theme.palette.background.paper,
 | 
					        width: '60%'
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SimpleTabs extends React.Component {
 | 
					class ResponsiveDrawer extends React.Component {
 | 
				
			||||||
    state = {
 | 
					    state = {
 | 
				
			||||||
        value: 0,
 | 
					        mobileOpen: false,
 | 
				
			||||||
 | 
					        key: 'Home',
 | 
				
			||||||
 | 
					        open: false
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handleChange = (event, value) => {
 | 
					    handleDrawerToggle = () => {
 | 
				
			||||||
        this.setState({ value });
 | 
					        this.setState(state => ({ mobileOpen: !state.mobileOpen }));
 | 
				
			||||||
    };
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    handleClick = () => {
 | 
				
			||||||
 | 
					        this.setState(state => ({ open: !state.open }));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    nav = (text) => {
 | 
				
			||||||
 | 
					        this.setState({
 | 
				
			||||||
 | 
					            key: text
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const { classes } = this.props;
 | 
					        const { classes, theme } = this.props;
 | 
				
			||||||
        const { value } = this.state;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					        const drawer = (
 | 
				
			||||||
    <div className={classes.root}>
 | 
					            <div>
 | 
				
			||||||
        <AppBar position="static">
 | 
					                <div className={classes.toolbar} />
 | 
				
			||||||
            <Tabs value={value} onChange={this.handleChange} centered>
 | 
					                <Divider />
 | 
				
			||||||
                <Tab label="Home" />
 | 
					                <List>
 | 
				
			||||||
                <Tab label="Report a Sighting"/>
 | 
					                    <ListItem button key='Home' onClick={() => this.nav('Home')}>
 | 
				
			||||||
                <Tab label="Sightings" />
 | 
					                        <ListItemIcon><HomeIcon /></ListItemIcon>
 | 
				
			||||||
                <Tab label="Trail-Cam Quiz" />
 | 
					                        <ListItemText primary='Home' />
 | 
				
			||||||
                <Tab label="View Map" />
 | 
					                    </ListItem>
 | 
				
			||||||
                <Tab label="Marten Info" />
 | 
					                    <ListItem button key='Report' onClick={() => this.nav('Report')}>
 | 
				
			||||||
            </Tabs>
 | 
					                        <ListItemIcon><AssignmentIcon /></ListItemIcon>
 | 
				
			||||||
        </AppBar>
 | 
					                        <ListItemText primary='Report' />
 | 
				
			||||||
        {value === 0 && <Home/>}
 | 
					                    </ListItem>
 | 
				
			||||||
        {value === 1 && <Report/>}
 | 
					                    <ListItem button key='Map' onClick={() => this.nav('Map')}>
 | 
				
			||||||
        {value === 2 && <SightingList/>}
 | 
					                        <ListItemIcon><MapIcon /></ListItemIcon>
 | 
				
			||||||
        {value === 3 && <Quiz/>}
 | 
					                        <ListItemText primary='Map' />
 | 
				
			||||||
        {value === 4 && <ViewMap/>}
 | 
					                    </ListItem>
 | 
				
			||||||
        {value === 5 && <Info/>}
 | 
					                    <ListItem button key='List' onClick={() => this.nav('List')}>
 | 
				
			||||||
    </div>
 | 
					                        <ListItemIcon><ListIcon /></ListItemIcon>
 | 
				
			||||||
    );
 | 
					                        <ListItemText primary='List' />
 | 
				
			||||||
 | 
					                    </ListItem>
 | 
				
			||||||
 | 
					                    <ListItem button onClick={this.handleClick}>
 | 
				
			||||||
 | 
					                        <ListItemIcon>
 | 
				
			||||||
 | 
					                            <SlideshowIcon />
 | 
				
			||||||
 | 
					                        </ListItemIcon>
 | 
				
			||||||
 | 
					                        <ListItemText inset primary="Quiz" />
 | 
				
			||||||
 | 
					                        {this.state.open ? <ExpandLess /> : <ExpandMore />}
 | 
				
			||||||
 | 
					                    </ListItem>
 | 
				
			||||||
 | 
					                    <Collapse in={this.state.open} timeout="auto" unmountOnExit>
 | 
				
			||||||
 | 
					                        <List component="div" disablePadding>
 | 
				
			||||||
 | 
					                            <ListItem button className={classes.nested} onClick={() => this.nav('Easy-Quiz')}>
 | 
				
			||||||
 | 
					                                <ListItemText inset primary="Easy" />
 | 
				
			||||||
 | 
					                            </ListItem>
 | 
				
			||||||
 | 
					                            <ListItem button className={classes.nested} onClick={() => this.nav('Medium-Quiz')}>
 | 
				
			||||||
 | 
					                                <ListItemText inset primary="Medium" />
 | 
				
			||||||
 | 
					                            </ListItem>
 | 
				
			||||||
 | 
					                            <ListItem button className={classes.nested} onClick={() => this.nav('Hard-Quiz')}>
 | 
				
			||||||
 | 
					                                <ListItemText inset primary="Hard" />
 | 
				
			||||||
 | 
					                            </ListItem>
 | 
				
			||||||
 | 
					                        </List>
 | 
				
			||||||
 | 
					                    </Collapse>
 | 
				
			||||||
 | 
					                </List>
 | 
				
			||||||
 | 
					                <Divider />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div className={classes.root}>
 | 
				
			||||||
 | 
					                <CssBaseline />
 | 
				
			||||||
 | 
					                <AppBar position="fixed" className={classes.appBar}>
 | 
				
			||||||
 | 
					                    <Toolbar>
 | 
				
			||||||
 | 
					                        <IconButton
 | 
				
			||||||
 | 
					                            color="inherit"
 | 
				
			||||||
 | 
					                            aria-label="Open drawer"
 | 
				
			||||||
 | 
					                            onClick={this.handleDrawerToggle}
 | 
				
			||||||
 | 
					                            className={classes.menuButton}
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            <MenuIcon />
 | 
				
			||||||
 | 
					                        </IconButton>
 | 
				
			||||||
 | 
					                        <Typography variant="title" color="inherit" noWrap>
 | 
				
			||||||
 | 
					                            Marten Tracker
 | 
				
			||||||
 | 
					                        </Typography>
 | 
				
			||||||
 | 
					                    </Toolbar>
 | 
				
			||||||
 | 
					                </AppBar>
 | 
				
			||||||
 | 
					                <nav className={classes.drawer}>
 | 
				
			||||||
 | 
					                    <Hidden smUp implementation="css">
 | 
				
			||||||
 | 
					                        <Drawer
 | 
				
			||||||
 | 
					                            container={this.props.container}
 | 
				
			||||||
 | 
					                            variant="temporary"
 | 
				
			||||||
 | 
					                            anchor={theme.direction === 'rtl' ? 'right' : 'left'}
 | 
				
			||||||
 | 
					                            open={this.state.mobileOpen}
 | 
				
			||||||
 | 
					                            onClose={this.handleDrawerToggle}
 | 
				
			||||||
 | 
					                            classes={{
 | 
				
			||||||
 | 
					                                paper: classes.drawerPaper,
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                            ModalProps={{
 | 
				
			||||||
 | 
					                                keepMounted: true, // Better open performance on mobile.
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            {drawer}
 | 
				
			||||||
 | 
					                        </Drawer>
 | 
				
			||||||
 | 
					                    </Hidden>
 | 
				
			||||||
 | 
					                    <Hidden xsDown implementation="css">
 | 
				
			||||||
 | 
					                        <Drawer
 | 
				
			||||||
 | 
					                            classes={{
 | 
				
			||||||
 | 
					                                paper: classes.drawerPaper,
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                            variant="permanent"
 | 
				
			||||||
 | 
					                            open
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            {drawer}
 | 
				
			||||||
 | 
					                        </Drawer>
 | 
				
			||||||
 | 
					                    </Hidden>
 | 
				
			||||||
 | 
					                </nav>
 | 
				
			||||||
 | 
					                <main className={classes.content}>
 | 
				
			||||||
 | 
					                    <div className={classes.toolbar} />
 | 
				
			||||||
 | 
					                    {this.state.key === 'Home' && <Home />}
 | 
				
			||||||
 | 
					                    {this.state.key === 'Report' && <Report />}
 | 
				
			||||||
 | 
					                    {this.state.key === 'Map' && <ViewMap />}
 | 
				
			||||||
 | 
					                    {this.state.key === 'List' && <SightingList />}
 | 
				
			||||||
 | 
					                    {this.state.key === 'Easy-Quiz' && <Quiz difficulty='Easy' />}
 | 
				
			||||||
 | 
					                    {this.state.key === 'Medium-Quiz' && <Quiz difficulty='Medium' />}
 | 
				
			||||||
 | 
					                    {this.state.key === 'Hard-Quiz' && <Quiz difficulty='Hard' />}
 | 
				
			||||||
 | 
					                </main>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SimpleTabs.propTypes = {
 | 
					ResponsiveDrawer.propTypes = {
 | 
				
			||||||
    classes: PropTypes.object.isRequired,
 | 
					    classes: PropTypes.object.isRequired,
 | 
				
			||||||
 | 
					    // Injected by the documentation to work in an iframe.
 | 
				
			||||||
 | 
					    // You won't need it on your project.
 | 
				
			||||||
 | 
					    container: PropTypes.object,
 | 
				
			||||||
 | 
					    theme: PropTypes.object.isRequired,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default withStyles(styles)(SimpleTabs);
 | 
					export default withStyles(styles, { withTheme: true })(ResponsiveDrawer);
 | 
				
			||||||
 | 
					 | 
				
			||||||
							
								
								
									
										297
									
								
								src/components/QuizGame.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								src/components/QuizGame.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,297 @@
 | 
				
			|||||||
 | 
					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 Quiz from 'react-quiz-component';
 | 
				
			||||||
 | 
					import { Typography } from '@material-ui/core';
 | 
				
			||||||
 | 
					import Button from '@material-ui/core/Button';
 | 
				
			||||||
 | 
					import RefreshIcon from '@material-ui/icons/Refresh';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Style for the tabs.
 | 
				
			||||||
 | 
					const styles = theme => ({
 | 
				
			||||||
 | 
					    root: {
 | 
				
			||||||
 | 
					        flexGrow: 1,
 | 
				
			||||||
 | 
					        backgroundColor: theme.palette.background.paper,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    button: {
 | 
				
			||||||
 | 
					        margin: theme.spacing.unit,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    rightIcon: {
 | 
				
			||||||
 | 
					        marginLeft: theme.spacing.unit,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class QuizGame extends React.Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Shuffles a given array.
 | 
				
			||||||
 | 
					     * @param {*} array The array passed in.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    shuffleArray = array => {
 | 
				
			||||||
 | 
					        let shuffled = array;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var j, x, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i = shuffled.length - 1; i > 0; i--) {
 | 
				
			||||||
 | 
					            j = Math.floor(Math.random() * (i + 1));
 | 
				
			||||||
 | 
					            x = shuffled[i];
 | 
				
			||||||
 | 
					            shuffled[i] = shuffled[j];
 | 
				
			||||||
 | 
					            shuffled[j] = x;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return shuffled;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reset = () => {
 | 
				
			||||||
 | 
					        this.setState({
 | 
				
			||||||
 | 
					            difficulty: this.pickDifficulty(this.props.difficulty),
 | 
				
			||||||
 | 
					            key: Math.random()
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    easy = {
 | 
				
			||||||
 | 
					        "quizTitle": "Trail Cam Quiz: Easy",
 | 
				
			||||||
 | 
					        "questions": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "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"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    medium = {
 | 
				
			||||||
 | 
					        "quizTitle": "Trail Cam Quiz: Medium",
 | 
				
			||||||
 | 
					        "questions": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "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"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hard = {
 | 
				
			||||||
 | 
					        "quizTitle": "Trail Cam Quiz: Hard",
 | 
				
			||||||
 | 
					        "questions": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "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"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * This function returns the
 | 
				
			||||||
 | 
					     * quiz data based on the difficulty
 | 
				
			||||||
 | 
					     * level passed into it.
 | 
				
			||||||
 | 
					     * @param {*} difficulty The difficulty setting passed in.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    pickDifficulty = difficulty => {
 | 
				
			||||||
 | 
					        let level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (difficulty) {
 | 
				
			||||||
 | 
					            case 'Easy':
 | 
				
			||||||
 | 
					                this.easy.questions = this.shuffleArray(this.easy.questions);
 | 
				
			||||||
 | 
					                level = this.easy;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 'Medium':
 | 
				
			||||||
 | 
					                this.medium.questions = this.shuffleArray(this.medium.questions);
 | 
				
			||||||
 | 
					                level = this.medium;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 'Hard':
 | 
				
			||||||
 | 
					                this.hard.questions = this.shuffleArray(this.hard.questions);
 | 
				
			||||||
 | 
					                level = this.hard;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return level;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // The state of the component.
 | 
				
			||||||
 | 
					    state = {
 | 
				
			||||||
 | 
					        difficulty: this.pickDifficulty(this.props.difficulty),
 | 
				
			||||||
 | 
					        key: Math.random()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Renders the quiz component.
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
 | 
					        const { classes } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            // Tabs
 | 
				
			||||||
 | 
					            <div className={classes.root}>
 | 
				
			||||||
 | 
					                <Typography variant="headline" align="center">
 | 
				
			||||||
 | 
					                    <Grid container justify="center">
 | 
				
			||||||
 | 
					                        <Quiz quiz={this.state.difficulty} key={this.state.key} />
 | 
				
			||||||
 | 
					                    </Grid>
 | 
				
			||||||
 | 
					                </Typography>
 | 
				
			||||||
 | 
					                <Typography align="center">
 | 
				
			||||||
 | 
					                    <Button variant="contained" color="default" className={classes.button} onClick={this.reset}>
 | 
				
			||||||
 | 
					                        Reset
 | 
				
			||||||
 | 
					                        <RefreshIcon className={classes.rightIcon} />
 | 
				
			||||||
 | 
					                    </Button>
 | 
				
			||||||
 | 
					                </Typography>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QuizGame.propTypes = {
 | 
				
			||||||
 | 
					    classes: PropTypes.object.isRequired
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default withStyles(styles)(QuizGame);
 | 
				
			||||||
@ -1,12 +1,18 @@
 | 
				
			|||||||
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';
 | 
				
			||||||
import MenuItem from '@material-ui/core/MenuItem';
 | 
					import MenuItem from '@material-ui/core/MenuItem';
 | 
				
			||||||
import TextField from '@material-ui/core/TextField';
 | 
					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 Button from '@material-ui/core/Button';
 | 
				
			||||||
import firebase from '../firebase.js';
 | 
					import firebase from '../firebase.js';
 | 
				
			||||||
import GoogleMap from '../components/ReportMap';
 | 
					import GoogleMap from '../components/ReportMap';
 | 
				
			||||||
 | 
					import Modal from '@material-ui/core/Modal';
 | 
				
			||||||
 | 
					import Typography from '@material-ui/core/Typography';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Styles that the different
 | 
					 * Styles that the different
 | 
				
			||||||
@ -14,80 +20,162 @@ import GoogleMap from '../components/ReportMap';
 | 
				
			|||||||
 * in. Mostly used for spacing.
 | 
					 * in. Mostly used for spacing.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const styles = theme => ({
 | 
					const styles = theme => ({
 | 
				
			||||||
  container: {
 | 
					    container: {
 | 
				
			||||||
    display: 'flex',
 | 
					        display: 'flex',
 | 
				
			||||||
    flexWrap: 'wrap',
 | 
					        flexWrap: 'wrap'
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  textField: {
 | 
					    textField: {
 | 
				
			||||||
    marginLeft: theme.spacing.unit * 2,
 | 
					        marginLeft: theme.spacing.unit * 2,
 | 
				
			||||||
    marginRight: theme.spacing.unit,
 | 
					        marginRight: theme.spacing.unit,
 | 
				
			||||||
    marginTop: theme.spacing.unit * 2,
 | 
					        marginTop: theme.spacing.unit * 2,
 | 
				
			||||||
    flexBasis: 280,
 | 
					        flexBasis: 280,
 | 
				
			||||||
    width: '90%'
 | 
					        width: '90%'
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  button: {
 | 
					    button: {
 | 
				
			||||||
    marginLeft: theme.spacing.unit * 2,
 | 
					        marginLeft: theme.spacing.unit * 2,
 | 
				
			||||||
    marginRight: theme.spacing.unit,
 | 
					        marginRight: theme.spacing.unit,
 | 
				
			||||||
    marginTop: theme.spacing.unit * 2,
 | 
					        marginTop: theme.spacing.unit * 2,
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  dense: {
 | 
					    dense: {
 | 
				
			||||||
    marginTop: 30,
 | 
					        marginTop: 30,
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  menu: {
 | 
					    close: {
 | 
				
			||||||
    width: 200,
 | 
					        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,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Function for formatting the
 | 
					 | 
				
			||||||
 * date as a string that
 | 
					 | 
				
			||||||
 * Material UI can use. We'll
 | 
					 | 
				
			||||||
 * also store the date like
 | 
					 | 
				
			||||||
 * this string in the database.
 | 
					 | 
				
			||||||
 * @param {*} date, Date passed in. 
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function formatDate(date) {
 | 
					 | 
				
			||||||
    var d = new Date(date),
 | 
					 | 
				
			||||||
        month = '' + (d.getMonth() + 1),
 | 
					 | 
				
			||||||
        day = '' + d.getDate(),
 | 
					 | 
				
			||||||
        year = d.getFullYear();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (month.length < 2) month = '0' + month;
 | 
					 | 
				
			||||||
    if (day.length < 2) day = '0' + day;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return [year, month, day].join('-');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 
 | 
					/** 
 | 
				
			||||||
 * Types of sightings. Label is what is
 | 
					 * Types of sightings. 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 sightingTypes = [
 | 
					const sightingTypes = [
 | 
				
			||||||
  {
 | 
					    {
 | 
				
			||||||
    value: 'visual',
 | 
					        value: 'visual',
 | 
				
			||||||
    label: 'Visual',
 | 
					        label: 'Visual',
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  {
 | 
					    {
 | 
				
			||||||
    value: 'roadkill',
 | 
					        value: 'roadkill',
 | 
				
			||||||
    label: 'Roadkill',
 | 
					        label: 'Roadkill',
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  {
 | 
					    {
 | 
				
			||||||
    value: 'trapped',
 | 
					        value: 'trapped',
 | 
				
			||||||
    label: 'Trapped',
 | 
					        label: 'Trapped',
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  {
 | 
					    {
 | 
				
			||||||
    value: 'viewed_tracks',
 | 
					        value: 'viewed_tracks',
 | 
				
			||||||
    label: 'Viewed Tracks',
 | 
					        label: 'Viewed Tracks',
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  {
 | 
					    {
 | 
				
			||||||
    value: 'photo',
 | 
					        value: 'photo',
 | 
				
			||||||
    label: 'Photo',
 | 
					        label: 'Photo',
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  {
 | 
					    {
 | 
				
			||||||
    value: 'other',
 | 
					        value: 'other',
 | 
				
			||||||
    label: 'Other',
 | 
					        label: 'Other',
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 
 | 
				
			||||||
 | 
					 * 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',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 
 | 
					/** 
 | 
				
			||||||
@ -97,246 +185,378 @@ const sightingTypes = [
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
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.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class ReportForm extends React.Component {
 | 
					class ReportForm extends React.Component {
 | 
				
			||||||
  /**
 | 
					    /**
 | 
				
			||||||
   * Component contructor. Currently
 | 
					     * Component contructor. Currently
 | 
				
			||||||
   * only used to bind event
 | 
					     * only used to bind event
 | 
				
			||||||
   * handlers.
 | 
					     * handlers.
 | 
				
			||||||
   */
 | 
					     */
 | 
				
			||||||
  constructor() {
 | 
					    constructor() {
 | 
				
			||||||
    super();
 | 
					        super();
 | 
				
			||||||
    this.handleSubmit = this.handleSubmit.bind(this);
 | 
					        this.handleSubmit = this.handleSubmit.bind(this);
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * State of form components.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  state = {
 | 
					 | 
				
			||||||
    date: formatDate(new Date()),
 | 
					 | 
				
			||||||
    time: '00:00',
 | 
					 | 
				
			||||||
    type: 'visual',
 | 
					 | 
				
			||||||
    confidence: '1',
 | 
					 | 
				
			||||||
    desc: '',
 | 
					 | 
				
			||||||
    lat: '',
 | 
					 | 
				
			||||||
    lng: ''
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Handles state change in form
 | 
					 | 
				
			||||||
   * components.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  handleChange = name => event => {
 | 
					 | 
				
			||||||
    this.setState({
 | 
					 | 
				
			||||||
      [name]: event.target.value,
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
  * Get the coordinates 
 | 
					 | 
				
			||||||
  * 
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
 getCoordinates = (lat,lng) => {
 | 
					 | 
				
			||||||
    let latitude = lat;
 | 
					 | 
				
			||||||
    let longitude = lng;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.setState({
 | 
					 | 
				
			||||||
        lat: latitude,
 | 
					 | 
				
			||||||
        lng: longitude
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Event listener for form.
 | 
					 | 
				
			||||||
   * When the form is submitted,
 | 
					 | 
				
			||||||
   * this function passes the
 | 
					 | 
				
			||||||
   * data along to Firebase.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  handleSubmit(e) {
 | 
					 | 
				
			||||||
    e.preventDefault();
 | 
					 | 
				
			||||||
    const sightingsRef = firebase.database().ref('sightings');
 | 
					 | 
				
			||||||
    const sighting = {
 | 
					 | 
				
			||||||
      type: this.state.type,
 | 
					 | 
				
			||||||
      confidence: this.state.confidence,
 | 
					 | 
				
			||||||
      date: this.state.date,
 | 
					 | 
				
			||||||
      time: this.state.time,
 | 
					 | 
				
			||||||
      desc: this.state.desc,
 | 
					 | 
				
			||||||
      lat: this.state.lat,
 | 
					 | 
				
			||||||
      lng: this.state.lng
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    sightingsRef.push(sighting);
 | 
					 | 
				
			||||||
    this.setState({
 | 
					 | 
				
			||||||
      date: formatDate(new Date()),
 | 
					 | 
				
			||||||
      time: '00:00',
 | 
					 | 
				
			||||||
      type: 'visual',
 | 
					 | 
				
			||||||
      confidence: '1',
 | 
					 | 
				
			||||||
      desc: '',
 | 
					 | 
				
			||||||
      lat: '',
 | 
					 | 
				
			||||||
      lng: ''
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * The render method for this component.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  render() {
 | 
					 | 
				
			||||||
    const { classes } = this.props;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The actual form.
 | 
					    * Function for formatting the
 | 
				
			||||||
 | 
					    * year as a string that
 | 
				
			||||||
 | 
					    * Material UI can use.
 | 
				
			||||||
 | 
					    * @param {*} date, Date passed in. 
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getYear = date => {
 | 
				
			||||||
 | 
					        var d = new Date(date),
 | 
				
			||||||
 | 
					            year = d.getFullYear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return year;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Function for formatting the
 | 
				
			||||||
 | 
					    * month as a string that
 | 
				
			||||||
 | 
					    * Material UI can use.
 | 
				
			||||||
 | 
					    * @param {*} date, Date passed in. 
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getMonth = date => {
 | 
				
			||||||
 | 
					        var d = new Date(date),
 | 
				
			||||||
 | 
					            month = d.getMonth() + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        month = month.toString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (month.length === 1) {
 | 
				
			||||||
 | 
					            month = "0" + month;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return month;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * State of form components.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    return (
 | 
					    state = {
 | 
				
			||||||
        <Fragment>
 | 
					        month: this.getMonth(new Date()),
 | 
				
			||||||
            <form className={classes.container} autoComplete="off" onSubmit={this.handleSubmit}>
 | 
					        year: this.getYear(new Date()),
 | 
				
			||||||
                <Grid container>
 | 
					        time: 'unknown',
 | 
				
			||||||
                    <Grid item xs={6}>
 | 
					        type: 'visual',
 | 
				
			||||||
                        <Grid container spacing={8}>
 | 
					        confidence: '1',
 | 
				
			||||||
                            <Grid item xs={12}>
 | 
					        desc: '',
 | 
				
			||||||
                                <TextField
 | 
					        lat: '',
 | 
				
			||||||
                                id="select-sighting-type"
 | 
					        lng: '',
 | 
				
			||||||
                                select
 | 
					        open: false,
 | 
				
			||||||
                                required
 | 
					        openModal: false, 
 | 
				
			||||||
                                name="sighting-type"
 | 
					        hasModalOpened: false
 | 
				
			||||||
                                label="Select"
 | 
					    };
 | 
				
			||||||
                                className={classes.textField}
 | 
					 | 
				
			||||||
                                value={this.state.type}
 | 
					 | 
				
			||||||
                                onChange={this.handleChange('type')}
 | 
					 | 
				
			||||||
                                SelectProps={{
 | 
					 | 
				
			||||||
                                    MenuProps: {
 | 
					 | 
				
			||||||
                                    className: classes.menu,
 | 
					 | 
				
			||||||
                                    },
 | 
					 | 
				
			||||||
                                }}
 | 
					 | 
				
			||||||
                                helperText="Please select type of sighting"
 | 
					 | 
				
			||||||
                                >
 | 
					 | 
				
			||||||
                                {sightingTypes.map(option => (
 | 
					 | 
				
			||||||
                                    <MenuItem key={option.value} value={option.value}>
 | 
					 | 
				
			||||||
                                    {option.label}
 | 
					 | 
				
			||||||
                                    </MenuItem>
 | 
					 | 
				
			||||||
                                ))}
 | 
					 | 
				
			||||||
                                </TextField>
 | 
					 | 
				
			||||||
                            </Grid>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            <Grid item xs={12}>
 | 
					    handleModalOpen = () => !this.state.hasModalOpened ? this.setState({ openModal: true, hasModalOpened: true }) : null;
 | 
				
			||||||
                                <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}>
 | 
					    handleModalClose = () => {
 | 
				
			||||||
                                <TextField
 | 
					        this.setState({ openModal: false });
 | 
				
			||||||
                                    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}>
 | 
					    getModalStyle = () => {
 | 
				
			||||||
                                <TextField
 | 
					        return {
 | 
				
			||||||
                                    id="sighting-time"
 | 
					            top: `25%`,
 | 
				
			||||||
                                    required
 | 
					            left: `75%`,
 | 
				
			||||||
                                    label="Sighting time"
 | 
					            transform: `translate(-25%, -75%)`,
 | 
				
			||||||
                                    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
 | 
					     * Handles state change in form
 | 
				
			||||||
                                id="sighting-description"
 | 
					     * components.
 | 
				
			||||||
                                required
 | 
					     */
 | 
				
			||||||
                                label="Description"
 | 
					    handleChange = name => event => {
 | 
				
			||||||
                                name="sighting-desc"
 | 
					        this.setState({
 | 
				
			||||||
                                multiline
 | 
					            [name]: event.target.value,
 | 
				
			||||||
                                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}>
 | 
					     * Handles closing the toast.
 | 
				
			||||||
                                    Submit
 | 
					     */
 | 
				
			||||||
                                </Button>
 | 
					    handleClose = (event, reason) => {
 | 
				
			||||||
 | 
					        if (reason === 'clickaway') {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.setState({ open: false });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					    * Get the coordinates 
 | 
				
			||||||
 | 
					    * 
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getCoordinates = (lat, lng) => {
 | 
				
			||||||
 | 
					        let latitude = lat;
 | 
				
			||||||
 | 
					        let longitude = lng;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.setState({
 | 
				
			||||||
 | 
					            lat: latitude,
 | 
				
			||||||
 | 
					            lng: longitude
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Event listener for form.
 | 
				
			||||||
 | 
					     * When the form is submitted,
 | 
				
			||||||
 | 
					     * this function passes the
 | 
				
			||||||
 | 
					     * data along to Firebase.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    handleSubmit(e) {
 | 
				
			||||||
 | 
					        e.preventDefault();
 | 
				
			||||||
 | 
					        const sightingsRef = firebase.database().ref('sightings');
 | 
				
			||||||
 | 
					        const sighting = {
 | 
				
			||||||
 | 
					            type: this.state.type,
 | 
				
			||||||
 | 
					            confidence: this.state.confidence,
 | 
				
			||||||
 | 
					            date: this.state.year + '-' + this.state.month,
 | 
				
			||||||
 | 
					            time: this.state.time,
 | 
				
			||||||
 | 
					            desc: this.state.desc,
 | 
				
			||||||
 | 
					            lat: this.state.lat,
 | 
				
			||||||
 | 
					            lng: this.state.lng
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        sightingsRef.push(sighting);
 | 
				
			||||||
 | 
					        this.setState({
 | 
				
			||||||
 | 
					            year: this.getYear(new Date()),
 | 
				
			||||||
 | 
					            month: this.getMonth(new Date()),
 | 
				
			||||||
 | 
					            time: 'unknown',
 | 
				
			||||||
 | 
					            type: 'visual',
 | 
				
			||||||
 | 
					            confidence: '1',
 | 
				
			||||||
 | 
					            desc: '',
 | 
				
			||||||
 | 
					            lat: '',
 | 
				
			||||||
 | 
					            lng: '',
 | 
				
			||||||
 | 
					            open: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The render method for this component.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
 | 
					        const { classes } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * The actual form.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <Fragment>
 | 
				
			||||||
 | 
					                <form className={classes.container} autoComplete="off" onSubmit={this.handleSubmit}>
 | 
				
			||||||
 | 
					                    <Grid container>
 | 
				
			||||||
 | 
					                        <Grid item xs={12} md={6}>
 | 
				
			||||||
 | 
					                            <Grid container spacing={8}>
 | 
				
			||||||
 | 
					                                <Grid item xs={12}>
 | 
				
			||||||
 | 
					                                    <TextField
 | 
				
			||||||
 | 
					                                        id="select-sighting-type"
 | 
				
			||||||
 | 
					                                        select
 | 
				
			||||||
 | 
					                                        required
 | 
				
			||||||
 | 
					                                        name="sighting-type"
 | 
				
			||||||
 | 
					                                        label="Select"
 | 
				
			||||||
 | 
					                                        className={classes.textField}
 | 
				
			||||||
 | 
					                                        value={this.state.type}
 | 
				
			||||||
 | 
					                                        onChange={this.handleChange('type')}
 | 
				
			||||||
 | 
					                                        SelectProps={{
 | 
				
			||||||
 | 
					                                            MenuProps: {
 | 
				
			||||||
 | 
					                                                className: classes.menu,
 | 
				
			||||||
 | 
					                                            },
 | 
				
			||||||
 | 
					                                        }}
 | 
				
			||||||
 | 
					                                        helperText="Please select type of sighting"
 | 
				
			||||||
 | 
					                                    >
 | 
				
			||||||
 | 
					                                        {sightingTypes.map(option => (
 | 
				
			||||||
 | 
					                                            <MenuItem key={option.value} value={option.value}>
 | 
				
			||||||
 | 
					                                                {option.label}
 | 
				
			||||||
 | 
					                                            </MenuItem>
 | 
				
			||||||
 | 
					                                        ))}
 | 
				
			||||||
 | 
					                                    </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="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>
 | 
					 | 
				
			||||||
                        </Grid>
 | 
					                        </Grid>
 | 
				
			||||||
                    <Grid item xs={6}>
 | 
					                        <Grid item xs={12} md={6} onMouseEnter={this.handleModalOpen}>
 | 
				
			||||||
                        <GoogleMap onClick={this.getCoordinates}/>
 | 
					                            <GoogleMap onClick={this.getCoordinates}/>
 | 
				
			||||||
 | 
					                            <Modal
 | 
				
			||||||
 | 
					                                aria-labelledby="simple-modal-title"
 | 
				
			||||||
 | 
					                                aria-describedby="simple-modal-description"
 | 
				
			||||||
 | 
					                                open={this.state.openModal}
 | 
				
			||||||
 | 
					                                onClose={this.handleModalClose}
 | 
				
			||||||
 | 
					                            >
 | 
				
			||||||
 | 
					                                <div style={this.getModalStyle()} className={classes.paper}>
 | 
				
			||||||
 | 
					                                    <Typography variant="title" id="modal-title">
 | 
				
			||||||
 | 
					                                        Need a little help?
 | 
				
			||||||
 | 
					                                    </Typography>
 | 
				
			||||||
 | 
					                                    <Typography variant="subheading" id="simple-modal-description">
 | 
				
			||||||
 | 
					                                        Click on the map to drop a pin!
 | 
				
			||||||
 | 
					                                    </Typography>
 | 
				
			||||||
 | 
					                                </div>
 | 
				
			||||||
 | 
					                            </Modal>
 | 
				
			||||||
 | 
					                        </Grid>
 | 
				
			||||||
                    </Grid>
 | 
					                    </Grid>
 | 
				
			||||||
                </Grid>
 | 
					                </form>
 | 
				
			||||||
            </form>
 | 
					                <Snackbar
 | 
				
			||||||
        </Fragment>
 | 
					                    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} />Report received.</span>}
 | 
				
			||||||
 | 
					                    action={[
 | 
				
			||||||
 | 
					                        <IconButton
 | 
				
			||||||
 | 
					                            key="close"
 | 
				
			||||||
 | 
					                            aria-label="Close"
 | 
				
			||||||
 | 
					                            color="inherit"
 | 
				
			||||||
 | 
					                            className={classes.close}
 | 
				
			||||||
 | 
					                            onClick={this.handleClose}
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            <CloseIcon />
 | 
				
			||||||
 | 
					                        </IconButton>,
 | 
				
			||||||
 | 
					                    ]}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					            </Fragment>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ReportForm.propTypes = {
 | 
					ReportForm.propTypes = {
 | 
				
			||||||
  classes: PropTypes.object.isRequired,
 | 
					    classes: PropTypes.object.isRequired,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default withStyles(styles)(ReportForm);
 | 
					export default withStyles(styles)(ReportForm);
 | 
				
			||||||
@ -9,7 +9,7 @@ const API_KEY = 'AIzaSyAZ_0J01bA6wCbIPK4UBq2RUBC-hIqG4mM';
 | 
				
			|||||||
const mapStyles = {
 | 
					const mapStyles = {
 | 
				
			||||||
    width: '100%',
 | 
					    width: '100%',
 | 
				
			||||||
    height: '100%'
 | 
					    height: '100%'
 | 
				
			||||||
}
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class MapContainer extends Component {
 | 
					export class MapContainer extends Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -18,22 +18,22 @@ export class MapContainer extends Component {
 | 
				
			|||||||
        if (navigator.geolocation) {
 | 
					        if (navigator.geolocation) {
 | 
				
			||||||
            navigator.geolocation.getCurrentPosition((position) => {
 | 
					            navigator.geolocation.getCurrentPosition((position) => {
 | 
				
			||||||
                this.setState({
 | 
					                this.setState({
 | 
				
			||||||
                        myLatLng: {
 | 
					                    myLatLng: {
 | 
				
			||||||
                            lat: position.coords.latitude,
 | 
					                        lat: position.coords.latitude,
 | 
				
			||||||
                            lng: position.coords.longitude
 | 
					                        lng: position.coords.longitude
 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // If browser doesn't support geolocation or if user does not allow it, 
 | 
					            // If browser doesn't support geolocation or if user does not allow it, 
 | 
				
			||||||
            // center map on Grand Rapids, Michigan
 | 
					            // center map on Grand Rapids, Michigan
 | 
				
			||||||
            this.setState({
 | 
					            this.setState({
 | 
				
			||||||
                    myLatLng: {
 | 
					                myLatLng: {
 | 
				
			||||||
                        lat: 42.9634,
 | 
					                    lat: 42.9634,
 | 
				
			||||||
                        lng: 85.6681
 | 
					                    lng: 85.6681
 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -68,13 +68,13 @@ export class MapContainer extends Component {
 | 
				
			|||||||
                lat: e.latLng.lat(),
 | 
					                lat: e.latLng.lat(),
 | 
				
			||||||
                lng: e.latLng.lng()
 | 
					                lng: e.latLng.lng()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        })
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let lat = e.latLng.lat();
 | 
					        let lat = e.latLng.lat();
 | 
				
			||||||
        let lng =  e.latLng.lng();
 | 
					        let lng = e.latLng.lng();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.props.onClick) {
 | 
					        if (this.props.onClick) {
 | 
				
			||||||
            this.props.onClick(lat,lng);
 | 
					            this.props.onClick(lat, lng);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -98,36 +98,36 @@ export class MapContainer extends Component {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            // Render the Google Map, Marker, and InfoWindow components
 | 
					            // Render the Google Map, Marker, and InfoWindow components
 | 
				
			||||||
            <div className = "report-google-map-container">
 | 
					            <div className="report-google-map-container">
 | 
				
			||||||
                <Map
 | 
					                <Map
 | 
				
			||||||
                    style = { mapStyles }
 | 
					                    style={mapStyles}
 | 
				
			||||||
                    google = { this.props.google }
 | 
					                    google={this.props.google}
 | 
				
			||||||
                    initialCenter = { this.state.myLatLng }
 | 
					                    initialCenter={this.state.myLatLng}
 | 
				
			||||||
                    center = { this.state.myLatLng }
 | 
					                    center={this.state.myLatLng}
 | 
				
			||||||
                    defaultZoom = { 15 }
 | 
					                    defaultZoom={15}
 | 
				
			||||||
                    onClick = { this.onMapClick } >
 | 
					                    onClick={this.onMapClick} >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <Marker
 | 
					                    <Marker
 | 
				
			||||||
                        position = { this.state.markerLatLng }
 | 
					                        position={this.state.markerLatLng}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <Marker
 | 
					                    <Marker
 | 
				
			||||||
                        position = { this.state.myLatLng }
 | 
					                        position={this.state.myLatLng}
 | 
				
			||||||
                        onClick = { this.onMarkerClick }
 | 
					                        onClick={this.onMarkerClick}
 | 
				
			||||||
                        title = { 'You are here' }
 | 
					                        title={'You are here'}
 | 
				
			||||||
                        name = { '' } 
 | 
					                        name={''}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <InfoWindow
 | 
					                    <InfoWindow
 | 
				
			||||||
                        marker = { this.state.activeMarker }
 | 
					                        marker={this.state.activeMarker}
 | 
				
			||||||
                        visible = { this.state.showingInfoWindow } >
 | 
					                        visible={this.state.showingInfoWindow} >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        <Fragment>
 | 
					                        <Fragment>
 | 
				
			||||||
                            <Typography variant = "display1" gutterBottom>
 | 
					                            <Typography variant="display1" gutterBottom>
 | 
				
			||||||
                                { this.state.selectedPlace.title }
 | 
					                                {this.state.selectedPlace.title}
 | 
				
			||||||
                            </Typography>
 | 
					                            </Typography>
 | 
				
			||||||
                            <Typography variant = "subheading" gutterBottom>
 | 
					                            <Typography variant="subheading" gutterBottom>
 | 
				
			||||||
                                { this.state.selectedPlace.name }
 | 
					                                {this.state.selectedPlace.name}
 | 
				
			||||||
                            </Typography>
 | 
					                            </Typography>
 | 
				
			||||||
                        </Fragment>
 | 
					                        </Fragment>
 | 
				
			||||||
                    </InfoWindow>
 | 
					                    </InfoWindow>
 | 
				
			||||||
@ -138,6 +138,4 @@ export class MapContainer extends Component {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Send the Google Map API Key with the MapContainer component
 | 
					// Send the Google Map API Key with the MapContainer component
 | 
				
			||||||
export default GoogleApiWrapper({
 | 
					export default GoogleApiWrapper({ apiKey: (API_KEY) })(MapContainer);
 | 
				
			||||||
    apiKey: (API_KEY)
 | 
					 | 
				
			||||||
})(MapContainer)
 | 
					 | 
				
			||||||
							
								
								
									
										160
									
								
								src/components/SightingDetail.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								src/components/SightingDetail.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,160 @@
 | 
				
			|||||||
 | 
					import React, { Component, Fragment } from 'react';
 | 
				
			||||||
 | 
					import Disqus from 'disqus-react';
 | 
				
			||||||
 | 
					import moment from 'moment';
 | 
				
			||||||
 | 
					import SightingDetailMap from './SightingDetailMap';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 
 | 
				
			||||||
 | 
					  * Types of sightings. Label is what is
 | 
				
			||||||
 | 
					  * viewed in the application, value is
 | 
				
			||||||
 | 
					  * what is stored in the database.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 const sightingTypes = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'visual',
 | 
				
			||||||
 | 
					        label: 'Visual',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'roadkill',
 | 
				
			||||||
 | 
					        label: 'Roadkill',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'trapped',
 | 
				
			||||||
 | 
					        label: 'Trapped',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'viewed_tracks',
 | 
				
			||||||
 | 
					        label: 'Viewed Tracks',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'photo',
 | 
				
			||||||
 | 
					        label: 'Photo',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'other',
 | 
				
			||||||
 | 
					        label: 'Other',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 
 | 
				
			||||||
 | 
					 * 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
 | 
				
			||||||
 | 
					 * viewed in the application, value is
 | 
				
			||||||
 | 
					 * what is stored in the database.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					const confidenceLevels = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '1',
 | 
				
			||||||
 | 
					        label: '1 - Strongly disagree',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '2',
 | 
				
			||||||
 | 
					        label: '2 - Disagree',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '3',
 | 
				
			||||||
 | 
					        label: '3 - Neutral',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '4',
 | 
				
			||||||
 | 
					        label: '4 - Agree',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '5',
 | 
				
			||||||
 | 
					        label: '5 - Strongly agree',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SightingDetail extends Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets formatted type value.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getType = item => {
 | 
				
			||||||
 | 
					        for (var i = 0; i < sightingTypes.length; i++) {
 | 
				
			||||||
 | 
					            if (sightingTypes[i].value === item) {
 | 
				
			||||||
 | 
					                return sightingTypes[i].label;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets formatted time value.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    getTime = item => {
 | 
				
			||||||
 | 
					        for (var i = 0; i < timeTypes.length; i++) {
 | 
				
			||||||
 | 
					            if (timeTypes[i].value === item) {
 | 
				
			||||||
 | 
					                return timeTypes[i].label;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets formatted confidence value.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getConfidence = item => {
 | 
				
			||||||
 | 
					        for (var i = 0; i < confidenceLevels.length; i++) {
 | 
				
			||||||
 | 
					            if (confidenceLevels[i].value === item) {
 | 
				
			||||||
 | 
					                return confidenceLevels[i].label;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    formatDate = date => {
 | 
				
			||||||
 | 
					        return (moment(date, "YYYY-MM").format("MMMM YYYY").toString());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
 | 
					        const disqusShortname = 'https-marten-application-netlify-com';
 | 
				
			||||||
 | 
					        const disqusConfig = {
 | 
				
			||||||
 | 
					            url: `http://localhost:3000/${this.props.detail.id}`,
 | 
				
			||||||
 | 
					            identifier: this.props.detail.id,
 | 
				
			||||||
 | 
					            title: this.props.detail.id
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <Fragment>
 | 
				
			||||||
 | 
					                <SightingDetailMap lat={this.props.detail.lat} lng={this.props.detail.lng} />
 | 
				
			||||||
 | 
					                <div className='sighting-details-content'>
 | 
				
			||||||
 | 
					                    <p><b>Type:</b> {this.getType(this.props.detail.type)}</p>
 | 
				
			||||||
 | 
					                    <p><b>When:</b> {this.formatDate(this.props.detail.date)}, {this.getTime(this.props.detail.time)}</p>
 | 
				
			||||||
 | 
					                    <p><b>Where:</b> {this.props.detail.lat} degrees N, and {this.props.detail.lng} degrees E</p>
 | 
				
			||||||
 | 
					                    <p><b>I am confident of my sighting:</b> {this.getConfidence(this.props.detail.confidence)}</p>
 | 
				
			||||||
 | 
					                    <hr/>
 | 
				
			||||||
 | 
					                    <p>{`${this.props.detail.desc}`}</p>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <Disqus.DiscussionEmbed shortname={disqusShortname} config={disqusConfig} />
 | 
				
			||||||
 | 
					            </Fragment>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default SightingDetail;
 | 
				
			||||||
							
								
								
									
										36
									
								
								src/components/SightingDetailMap.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/components/SightingDetailMap.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					import React, { Component } from 'react';
 | 
				
			||||||
 | 
					import { Map, Marker, GoogleApiWrapper } from 'google-maps-react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Google Maps API Key
 | 
				
			||||||
 | 
					const API_KEY = 'AIzaSyAZ_0J01bA6wCbIPK4UBq2RUBC-hIqG4mM';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Map container styles
 | 
				
			||||||
 | 
					const mapStyles = {
 | 
				
			||||||
 | 
					    width: '100%',
 | 
				
			||||||
 | 
					    height: '100%'
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class MapContainer extends Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            // Render the Google Map, Marker, and InfoWindow components
 | 
				
			||||||
 | 
					            <div className="sighting-detail-google-map-container">
 | 
				
			||||||
 | 
					                <Map
 | 
				
			||||||
 | 
					                    style={mapStyles}
 | 
				
			||||||
 | 
					                    google={this.props.google}
 | 
				
			||||||
 | 
					                    initialCenter={{ lat: this.props.lat, lng: this.props.lng }}
 | 
				
			||||||
 | 
					                    center={{ lat: this.props.lat, lng: this.props.lng }}
 | 
				
			||||||
 | 
					                    defaultZoom={15}>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <Marker
 | 
				
			||||||
 | 
					                        position={{ lat: this.props.lat, lng: this.props.lng }}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                </Map>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Send the Google Map API Key with the MapContainer component
 | 
				
			||||||
 | 
					export default GoogleApiWrapper({ apiKey: (API_KEY) })(MapContainer);
 | 
				
			||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
import React, { Component, Fragment } from 'react';
 | 
					import React, { Component, Fragment } from 'react';
 | 
				
			||||||
import { Map, InfoWindow, Marker, GoogleApiWrapper } from 'google-maps-react';
 | 
					import { Map, InfoWindow, Marker, GoogleApiWrapper } from 'google-maps-react';
 | 
				
			||||||
 | 
					import moment from 'moment';
 | 
				
			||||||
import Typography from '@material-ui/core/Typography';
 | 
					import Typography from '@material-ui/core/Typography';
 | 
				
			||||||
import firebase from '../firebase.js';
 | 
					import firebase from '../firebase.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,7 +11,95 @@ const API_KEY = 'AIzaSyAZ_0J01bA6wCbIPK4UBq2RUBC-hIqG4mM';
 | 
				
			|||||||
const mapStyles = {
 | 
					const mapStyles = {
 | 
				
			||||||
    width: '100%',
 | 
					    width: '100%',
 | 
				
			||||||
    height: '100%'
 | 
					    height: '100%'
 | 
				
			||||||
}
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 
 | 
				
			||||||
 | 
					  * Types of sightings. Label is what is
 | 
				
			||||||
 | 
					  * viewed in the application, value is
 | 
				
			||||||
 | 
					  * what is stored in the database.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const sightingTypes = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'visual',
 | 
				
			||||||
 | 
					        label: 'Visual',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'roadkill',
 | 
				
			||||||
 | 
					        label: 'Roadkill',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'trapped',
 | 
				
			||||||
 | 
					        label: 'Trapped',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'viewed_tracks',
 | 
				
			||||||
 | 
					        label: 'Viewed Tracks',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'photo',
 | 
				
			||||||
 | 
					        label: 'Photo',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: 'other',
 | 
				
			||||||
 | 
					        label: 'Other',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 
 | 
				
			||||||
 | 
					 * 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
 | 
				
			||||||
 | 
					 * viewed in the application, value is
 | 
				
			||||||
 | 
					 * what is stored in the database.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					const confidenceLevels = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '1',
 | 
				
			||||||
 | 
					        label: '1 - Strongly disagree',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '2',
 | 
				
			||||||
 | 
					        label: '2 - Disagree',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '3',
 | 
				
			||||||
 | 
					        label: '3 - Neutral',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '4',
 | 
				
			||||||
 | 
					        label: '4 - Agree',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value: '5',
 | 
				
			||||||
 | 
					        label: '5 - Strongly agree',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class MapContainer extends Component {
 | 
					export class MapContainer extends Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -19,26 +108,59 @@ export class MapContainer extends Component {
 | 
				
			|||||||
        if (navigator.geolocation) {
 | 
					        if (navigator.geolocation) {
 | 
				
			||||||
            navigator.geolocation.getCurrentPosition((position) => {
 | 
					            navigator.geolocation.getCurrentPosition((position) => {
 | 
				
			||||||
                this.setState({
 | 
					                this.setState({
 | 
				
			||||||
                        myLatLng: {
 | 
					                    myLatLng: {
 | 
				
			||||||
                            lat: position.coords.latitude,
 | 
					                        lat: position.coords.latitude,
 | 
				
			||||||
                            lng: position.coords.longitude
 | 
					                        lng: position.coords.longitude
 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                );
 | 
					                });
 | 
				
			||||||
            })
 | 
					            });
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // If browser doesn't support geolocation or if user does not allow it, 
 | 
					            // If browser doesn't support geolocation or if user does not allow it, 
 | 
				
			||||||
            // center map on Grand Rapids, Michigan
 | 
					            // center map on Grand Rapids, Michigan
 | 
				
			||||||
            this.setState({
 | 
					            this.setState({
 | 
				
			||||||
                    myLatLng: {
 | 
					                myLatLng: {
 | 
				
			||||||
                        lat: 42.9634,
 | 
					                    lat: 42.9634,
 | 
				
			||||||
                        lng: 85.6681
 | 
					                    lng: 85.6681
 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            );
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets formatted type value.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getType = item => {
 | 
				
			||||||
 | 
					        for (var i = 0; i < sightingTypes.length; i++) {
 | 
				
			||||||
 | 
					            if (sightingTypes[i].value === item) {
 | 
				
			||||||
 | 
					                return sightingTypes[i].label;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets formatted time value.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    getTime = item => {
 | 
				
			||||||
 | 
					        for (var i = 0; i < timeTypes.length; i++) {
 | 
				
			||||||
 | 
					            if (timeTypes[i].value === item) {
 | 
				
			||||||
 | 
					                return timeTypes[i].label;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					    * Gets formatted confidence value.
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					    getConfidence = item => {
 | 
				
			||||||
 | 
					        for (var i = 0; i < confidenceLevels.length; i++) {
 | 
				
			||||||
 | 
					            if (confidenceLevels[i].value === item) {
 | 
				
			||||||
 | 
					                return confidenceLevels[i].label;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // When the component has mounted to the DOM, get the user's location
 | 
					    // When the component has mounted to the DOM, get the user's location
 | 
				
			||||||
    componentDidMount() {
 | 
					    componentDidMount() {
 | 
				
			||||||
        this.getLocation();
 | 
					        this.getLocation();
 | 
				
			||||||
@ -104,10 +226,13 @@ export class MapContainer extends Component {
 | 
				
			|||||||
            default:
 | 
					            default:
 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        return pinIcon
 | 
					        return pinIcon
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    formatDate = date => {
 | 
				
			||||||
 | 
					        return (moment(date, "YYYY-MM").format("MMMM YYYY").toString());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set the state of the component to contain user coordinates and initial 
 | 
					    // Set the state of the component to contain user coordinates and initial 
 | 
				
			||||||
    // marker and info window information
 | 
					    // marker and info window information
 | 
				
			||||||
    state = {
 | 
					    state = {
 | 
				
			||||||
@ -119,42 +244,43 @@ export class MapContainer extends Component {
 | 
				
			|||||||
        activeMarker: {},
 | 
					        activeMarker: {},
 | 
				
			||||||
        selectedPlace: {},
 | 
					        selectedPlace: {},
 | 
				
			||||||
        sightings: []
 | 
					        sightings: []
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const {google} = this.props;
 | 
					        const {google} = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            // Render the Google Map, Marker, and InfoWindow components
 | 
					            // Render the Google Map, Marker, and InfoWindow components
 | 
				
			||||||
            <div className = "sighting-google-map-container">
 | 
					            <div className="sighting-google-map-container">
 | 
				
			||||||
                <Map
 | 
					                <Map
 | 
				
			||||||
                    style = { mapStyles }
 | 
					                    style={mapStyles}
 | 
				
			||||||
                    google = { this.props.google }
 | 
					                    google={this.props.google}
 | 
				
			||||||
                    initialCenter = { this.state.myLatLng }
 | 
					                    initialCenter={this.state.myLatLng}
 | 
				
			||||||
                    center = { this.state.myLatLng }
 | 
					                    center={this.state.myLatLng}
 | 
				
			||||||
                    defaultZoom = { 15 }
 | 
					                    defaultZoom={15}
 | 
				
			||||||
                    onClick = { this.onMapClick } >
 | 
					                    onClick={this.onMapClick}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <Marker
 | 
					                    <Marker
 | 
				
			||||||
                        position = { this.state.myLatLng }
 | 
					                        position={this.state.myLatLng}
 | 
				
			||||||
                        onClick = { this.onMarkerClick }
 | 
					                        onClick={this.onMarkerClick}
 | 
				
			||||||
                        type = { 'You are here' } 
 | 
					                        type={'You are here'}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    { this.state.sightings.map((sighting) => {
 | 
					                    {this.state.sightings.map((sighting) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        let pinIcon = this.sightingIcon(sighting.type)
 | 
					                        let pinIcon = this.sightingIcon(sighting.type)
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
                        return (
 | 
					                        return (
 | 
				
			||||||
                            <Marker
 | 
					                            <Marker
 | 
				
			||||||
                                key={ sighting.id }
 | 
					                                key={sighting.id}
 | 
				
			||||||
                                position={{ lat: sighting.lat, lng:sighting.lng }}
 | 
					                                position={{ lat: sighting.lat, lng: sighting.lng }}
 | 
				
			||||||
                                onClick = { this.onMarkerClick }
 | 
					                                onClick={this.onMarkerClick}
 | 
				
			||||||
                                type = { 'Type: ' + sighting.type }
 | 
					                                type={'Type: ' + this.getType(sighting.type)}
 | 
				
			||||||
                                confidence = { 'Confidence: ' + sighting.confidence }
 | 
					                                date={<Fragment><b>Date:</b> {this.formatDate(sighting.date)}</Fragment>}
 | 
				
			||||||
                                date = { 'Date: ' + sighting.date }
 | 
					                                time={<Fragment><b>Time:</b> {this.getTime(sighting.time)}</Fragment>}
 | 
				
			||||||
                                time = { 'Time: ' + sighting.time }
 | 
					                                confidence={<Fragment><b>I am confident of my sighting:</b> {this.getConfidence(sighting.confidence)}</Fragment>}
 | 
				
			||||||
                                description = { 'Description: ' + sighting.desc }
 | 
					                                description={<Fragment><b>Description:</b> {sighting.desc}</Fragment>}
 | 
				
			||||||
                                icon={{
 | 
					                                icon={{
 | 
				
			||||||
                                    url: pinIcon,
 | 
					                                    url: pinIcon,
 | 
				
			||||||
                                    anchor: new google.maps.Point(32,32),
 | 
					                                    anchor: new google.maps.Point(32,32),
 | 
				
			||||||
@ -165,24 +291,24 @@ export class MapContainer extends Component {
 | 
				
			|||||||
                    })}
 | 
					                    })}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <InfoWindow
 | 
					                    <InfoWindow
 | 
				
			||||||
                        marker = { this.state.activeMarker }
 | 
					                        marker={this.state.activeMarker}
 | 
				
			||||||
                        visible = { this.state.showingInfoWindow } >
 | 
					                        visible={this.state.showingInfoWindow} >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        <Fragment>
 | 
					                        <Fragment>
 | 
				
			||||||
                            <Typography variant = "display1" gutterBottom>
 | 
					                            <Typography variant="display1" gutterBottom>
 | 
				
			||||||
                                { this.state.selectedPlace.type }
 | 
					                                {this.state.selectedPlace.type}
 | 
				
			||||||
                            </Typography>
 | 
					                            </Typography>
 | 
				
			||||||
                            <Typography variant = "subheading" gutterBottom>
 | 
					                            <Typography variant="subheading" gutterBottom>
 | 
				
			||||||
                                { this.state.selectedPlace.confidence }
 | 
					                                {this.state.selectedPlace.date}
 | 
				
			||||||
                            </Typography>
 | 
					                            </Typography>
 | 
				
			||||||
                            <Typography variant = "subheading" gutterBottom>
 | 
					                            <Typography variant="subheading" gutterBottom>
 | 
				
			||||||
                                { this.state.selectedPlace.date }
 | 
					                                {this.state.selectedPlace.time}
 | 
				
			||||||
                            </Typography>
 | 
					                            </Typography>
 | 
				
			||||||
                            <Typography variant = "subheading" gutterBottom>
 | 
					                            <Typography variant="subheading" gutterBottom>
 | 
				
			||||||
                                { this.state.selectedPlace.time }
 | 
					                                {this.state.selectedPlace.confidence}
 | 
				
			||||||
                            </Typography>
 | 
					                            </Typography>
 | 
				
			||||||
                            <Typography variant = "subheading" gutterBottom>
 | 
					                            <Typography variant="subheading" gutterBottom>
 | 
				
			||||||
                                { this.state.selectedPlace.description }
 | 
					                                {this.state.selectedPlace.description}
 | 
				
			||||||
                            </Typography>
 | 
					                            </Typography>
 | 
				
			||||||
                        </Fragment>
 | 
					                        </Fragment>
 | 
				
			||||||
                    </InfoWindow>
 | 
					                    </InfoWindow>
 | 
				
			||||||
@ -193,6 +319,4 @@ export class MapContainer extends Component {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Send the Google Map API Key with the MapContainer component
 | 
					// Send the Google Map API Key with the MapContainer component
 | 
				
			||||||
export default GoogleApiWrapper({
 | 
					export default GoogleApiWrapper({ apiKey: (API_KEY) })(MapContainer);
 | 
				
			||||||
    apiKey: (API_KEY)
 | 
					 | 
				
			||||||
})(MapContainer)
 | 
					 | 
				
			||||||
@ -1,232 +1,95 @@
 | 
				
			|||||||
import React, {Fragment} from 'react';
 | 
					import React, { Component, Fragment } from 'react';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					 | 
				
			||||||
import Grid from '@material-ui/core/Grid';
 | 
					import Grid from '@material-ui/core/Grid';
 | 
				
			||||||
import TextField from '@material-ui/core/TextField'
 | 
					 | 
				
			||||||
import Button from '@material-ui/core/Button'
 | 
					 | 
				
			||||||
import Paper from '@material-ui/core/Paper'
 | 
					 | 
				
			||||||
import { withStyles } from '@material-ui/core/styles';
 | 
					 | 
				
			||||||
import Typography from '@material-ui/core/Typography';
 | 
					 | 
				
			||||||
import firebase from '../firebase.js';
 | 
					import firebase from '../firebase.js';
 | 
				
			||||||
 | 
					import List from '@material-ui/core/List';
 | 
				
			||||||
 | 
					import ListItem from '@material-ui/core/ListItem';
 | 
				
			||||||
 | 
					import ListItemText from '@material-ui/core/ListItemText';
 | 
				
			||||||
 | 
					import SightingDetail from './SightingDetail';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const styles = theme => ({
 | 
					class ViewSightings extends Component {
 | 
				
			||||||
    root: {
 | 
					 | 
				
			||||||
      ...theme.mixins.gutters(),
 | 
					 | 
				
			||||||
      paddingTop: theme.spacing.unit * 2,
 | 
					 | 
				
			||||||
      paddingBottom: theme.spacing.unit * 2,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    container: {
 | 
					 | 
				
			||||||
        display: 'flex',
 | 
					 | 
				
			||||||
        flexWrap: 'wrap',
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    textField: {
 | 
					 | 
				
			||||||
        marginLeft: theme.spacing.unit * 2,
 | 
					 | 
				
			||||||
        marginRight: theme.spacing.unit * 2,
 | 
					 | 
				
			||||||
        marginTop: theme.spacing.unit * 2,
 | 
					 | 
				
			||||||
        flexBasis: 280,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    button: {
 | 
					 | 
				
			||||||
        marginLeft: theme.spacing.unit * 3,
 | 
					 | 
				
			||||||
        marginRight: theme.spacing.unit * 3,
 | 
					 | 
				
			||||||
        marginTop: theme.spacing.unit * 3,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    paper: {
 | 
					 | 
				
			||||||
        marginLeft: theme.spacing.unit * 2,
 | 
					 | 
				
			||||||
        marginRight: theme.spacing.unit,
 | 
					 | 
				
			||||||
        marginTop: theme.spacing.unit * 2,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** 
 | 
					    componentDidMount() {
 | 
				
			||||||
  * Types of sightings. Label is what is
 | 
					        const sightingsRef = firebase.database().ref('sightings');
 | 
				
			||||||
  * viewed in the application, value is
 | 
					 | 
				
			||||||
  * what is stored in the database.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  const sightingTypes = [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      value: 'visual',
 | 
					 | 
				
			||||||
      label: 'Visual',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      value: 'roadkill',
 | 
					 | 
				
			||||||
      label: 'Roadkill',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      value: 'trapped',
 | 
					 | 
				
			||||||
      label: 'Trapped',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      value: 'viewed_tracks',
 | 
					 | 
				
			||||||
      label: 'Viewed Tracks',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      value: 'photo',
 | 
					 | 
				
			||||||
      label: 'Photo',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      value: 'other',
 | 
					 | 
				
			||||||
      label: 'Other',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** 
 | 
					        sightingsRef.on('value', (snapshot) => {
 | 
				
			||||||
   * Levels of confidence. Label is what is
 | 
					            let sightings = snapshot.val();
 | 
				
			||||||
   * viewed in the application, value is
 | 
					            let newState = [];
 | 
				
			||||||
   * what is stored in the database.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  const confidenceLevels = [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        value: '1',
 | 
					 | 
				
			||||||
        label: '1 - Strongly unconfident',
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        value: '2',
 | 
					 | 
				
			||||||
        label: '2 - Unconfident',
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        value: '3',
 | 
					 | 
				
			||||||
        label: '3 - Somewhat confident',
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        value: '4',
 | 
					 | 
				
			||||||
        label: '4 - Confident',
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        value: '5',
 | 
					 | 
				
			||||||
        label: '5 - Very confident',
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    ];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					            for (let sighting in sightings) {
 | 
				
			||||||
     * Gets formatted confidence value.
 | 
					                newState.unshift({
 | 
				
			||||||
     */
 | 
					                    id: sighting,
 | 
				
			||||||
    function getConfidence(item) {
 | 
					                    lat: sightings[sighting].lat,
 | 
				
			||||||
        for (var i = 0; i < confidenceLevels.length; i++) {
 | 
					                    lng: sightings[sighting].lng,
 | 
				
			||||||
            if (confidenceLevels[i].value === item) {
 | 
					                    desc: sightings[sighting].desc,
 | 
				
			||||||
                return confidenceLevels[i].label;
 | 
					                    type: sightings[sighting].type,
 | 
				
			||||||
 | 
					                    confidence: sightings[sighting].confidence,
 | 
				
			||||||
 | 
					                    date: sightings[sighting].date,
 | 
				
			||||||
 | 
					                    time: sightings[sighting].time
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					            this.setState({
 | 
				
			||||||
        
 | 
					                sightings: newState
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    getDetail = (id, lat, lng, desc, type, confidence, date, time) => {
 | 
				
			||||||
     * Gets formatted type value.
 | 
					        this.setState({
 | 
				
			||||||
     */
 | 
					            selectedSighting: {
 | 
				
			||||||
    function getType(item) {
 | 
					                id: id,
 | 
				
			||||||
        for (var i = 0; i < sightingTypes.length; i++) {
 | 
					                lat: lat,
 | 
				
			||||||
            if (sightingTypes[i].value === item) {
 | 
					                lng: lng,
 | 
				
			||||||
                return sightingTypes[i].label;
 | 
					                desc: desc,
 | 
				
			||||||
            }
 | 
					                type: type,
 | 
				
			||||||
        }
 | 
					                confidence: confidence,
 | 
				
			||||||
    }
 | 
					                date: date,
 | 
				
			||||||
 | 
					                time: time
 | 
				
			||||||
class ViewSightings extends React.Component {
 | 
					            },
 | 
				
			||||||
    constructor(props){
 | 
					            clicked: true
 | 
				
			||||||
       super(props);
 | 
					        })
 | 
				
			||||||
 | 
					 | 
				
			||||||
       this.handleSubmit = this.handleSubmit.bind(this);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state = {
 | 
					    state = {
 | 
				
			||||||
        id: '',
 | 
					        sightings: [],
 | 
				
			||||||
        type: 'N/A',
 | 
					        selectedSighting: {
 | 
				
			||||||
        confidence: 'N/A',
 | 
					            id: null,
 | 
				
			||||||
        date: 'N/A',
 | 
					            lat: null,
 | 
				
			||||||
        time: 'N/A',
 | 
					            lng: null,
 | 
				
			||||||
        desc: 'N/A',
 | 
					            desc: null,
 | 
				
			||||||
        lat: 'N/A',
 | 
					            type: null,
 | 
				
			||||||
        lng: 'N/A'
 | 
					            confidence: null,
 | 
				
			||||||
 | 
					            date: null,
 | 
				
			||||||
 | 
					            time: null
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        clicked: false
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Handles state change.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    handleChange = name => event => {
 | 
					 | 
				
			||||||
        this.setState({
 | 
					 | 
				
			||||||
        [name]: event.target.value,
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Handles submit on search.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    handleSubmit(e){
 | 
					 | 
				
			||||||
        e.preventDefault();
 | 
					 | 
				
			||||||
        const itemSighting = firebase.database().ref("sightings/" + this.state.id);
 | 
					 | 
				
			||||||
        itemSighting.once("value").then((snapshot) => {
 | 
					 | 
				
			||||||
            // Die if there's no data for that ID.
 | 
					 | 
				
			||||||
            if (!snapshot.exists()) {
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            let data = snapshot.val();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            this.setState({
 | 
					 | 
				
			||||||
                date: data.date,
 | 
					 | 
				
			||||||
                time: data.time,
 | 
					 | 
				
			||||||
                type: getType(data.type),
 | 
					 | 
				
			||||||
                confidence: getConfidence(data.confidence),
 | 
					 | 
				
			||||||
                desc: data.desc,
 | 
					 | 
				
			||||||
                lat: data.lat,
 | 
					 | 
				
			||||||
                lng: data.lng
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render(){
 | 
					 | 
				
			||||||
        const { classes } = this.props;
 | 
					 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            /**
 | 
					 | 
				
			||||||
             * The below houses the search
 | 
					 | 
				
			||||||
             * and submit button along with
 | 
					 | 
				
			||||||
             * the sighting information
 | 
					 | 
				
			||||||
             * it pulls.
 | 
					 | 
				
			||||||
             */
 | 
					 | 
				
			||||||
            <Fragment>
 | 
					            <Fragment>
 | 
				
			||||||
                <Grid container justify="center">
 | 
					                <Grid container>
 | 
				
			||||||
                    <form className={classes.container} onSubmit={this.handleSubmit}>
 | 
					                    <Grid item xs={12} md={6} className='sighting-list'>
 | 
				
			||||||
                    <Grid item xs={6}>
 | 
					                        <Fragment>
 | 
				
			||||||
                        <TextField
 | 
					                            <List>
 | 
				
			||||||
                        id="sighting-id"
 | 
					                            { 
 | 
				
			||||||
                        name="sighting-id"
 | 
					                                this.state.sightings.map((sighting) => {
 | 
				
			||||||
                        label="Input ID"
 | 
					                                    return (
 | 
				
			||||||
                        value={this.state.id}
 | 
					                                        <ListItem button key={ sighting.id } onClick={() => this.getDetail(sighting.id, sighting.lat, sighting.lng, sighting.desc, sighting.type, sighting.confidence, sighting.date, sighting.time)}>
 | 
				
			||||||
                        margin="normal"
 | 
					                                            <ListItemText primary={`${sighting.desc}`}/>
 | 
				
			||||||
                        onChange={this.handleChange('id')}
 | 
					                                        </ListItem>
 | 
				
			||||||
                        />
 | 
					                                    );
 | 
				
			||||||
 | 
					                                })
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            </List>
 | 
				
			||||||
 | 
					                        </Fragment>
 | 
				
			||||||
                    </Grid>
 | 
					                    </Grid>
 | 
				
			||||||
                    <Grid item xs={6}>
 | 
					                    <Grid item xs={12} md={6} className='sighting-details'>
 | 
				
			||||||
                        <Button variant="contained" type="submit" color="primary" className={classes.button}>
 | 
					                        {this.state.clicked === true && <SightingDetail detail={ this.state.selectedSighting }/>}
 | 
				
			||||||
                            Submit
 | 
					 | 
				
			||||||
                        </Button>
 | 
					 | 
				
			||||||
                    </Grid>
 | 
					 | 
				
			||||||
                    </form>
 | 
					 | 
				
			||||||
                    <Grid item xs={12}>
 | 
					 | 
				
			||||||
                        <Paper elevation={2}>
 | 
					 | 
				
			||||||
                            <Typography variant="headline" component="h3">
 | 
					 | 
				
			||||||
                            Sighting
 | 
					 | 
				
			||||||
                            </Typography>
 | 
					 | 
				
			||||||
                            <Typography component="p">
 | 
					 | 
				
			||||||
                            <b>Type:</b> {this.state.type} {<br/>}
 | 
					 | 
				
			||||||
                            <b>Confidence:</b> {this.state.confidence} {<br/>}
 | 
					 | 
				
			||||||
                            <b>Date:</b> {this.state.date} {<br/>}
 | 
					 | 
				
			||||||
                            <b>Time:</b> {this.state.time} {<br/>}
 | 
					 | 
				
			||||||
                            <b>Latitude:</b> {this.state.lat} {<br/>}
 | 
					 | 
				
			||||||
                            <b>Longitude:</b> {this.state.lng} {<br/>}
 | 
					 | 
				
			||||||
                            <b>Description:</b> {this.state.desc}
 | 
					 | 
				
			||||||
                            </Typography>
 | 
					 | 
				
			||||||
                        </Paper>
 | 
					 | 
				
			||||||
                    </Grid>
 | 
					                    </Grid>
 | 
				
			||||||
                </Grid>
 | 
					                </Grid>
 | 
				
			||||||
            </Fragment>
 | 
					            </Fragment>
 | 
				
			||||||
        )
 | 
					        );
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ViewSightings.propTypes = {
 | 
					export default ViewSightings;
 | 
				
			||||||
    classes: PropTypes.object.isRequired,
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default withStyles(styles)(ViewSightings);
 | 
					 | 
				
			||||||
@ -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",
 | 
				
			||||||
 | 
				
			|||||||
@ -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
									
								
							
							
						
						
									
										13
									
								
								src/pages/QuizPage.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import React, { Component } from 'react';
 | 
				
			||||||
 | 
					import QuizGame from '../components/QuizGame';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class QuizPage extends Component {
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <QuizGame difficulty={this.props.difficulty}/>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default QuizPage;
 | 
				
			||||||
@ -1,13 +1,10 @@
 | 
				
			|||||||
import React, { Component } from 'react';
 | 
					import React, { Component } from 'react';
 | 
				
			||||||
import ViewSightings from '../components/ViewSightings.js';
 | 
					import ViewSightings from '../components/ViewSightings.js';
 | 
				
			||||||
import Typography from '@material-ui/core/Typography';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Sighting extends Component {
 | 
					class Sighting extends Component {
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <Typography variant='display1' align='center' gutterBottom>
 | 
					            <ViewSightings/>
 | 
				
			||||||
                <ViewSightings/>
 | 
					 | 
				
			||||||
            </Typography>
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user