diff --git a/README.md b/README.md index 3d3ae18..17cbf89 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ https://app.circleci.com/pipelines/github/CPSECapstone ## Glossary -**UserInterface-as-a-Service** Date and UI compenents that can be effortlessly inserted into any apllications UI +**UserInterface-as-a-Service** Date and UI components that can be effortlessly inserted into any apllications UI **Tokenization** The process of turning sensitive pieces of data into a non-sensitive random string of characters that has no value if breached. diff --git a/frontend/src/app/index.js b/frontend/src/app/index.js index 505882d..8439326 100644 --- a/frontend/src/app/index.js +++ b/frontend/src/app/index.js @@ -14,10 +14,12 @@ import { Provider } from 'react-redux'; import store from '../store'; import NavBar from '../components/NavBar/NavBar'; -import Register from '../pages/Register'; -import Login from '../pages/Login'; +import Register from '../pages/Register/Register'; +import Login from '../pages/Login/Login'; import Home from '../pages/Home/Home'; import PrivateRoute from '../components/private-route/PrivateRoute'; +import NewPage from '../components/NewPage/NewPage'; + // Check for token to keep user logged in if (localStorage.jwtToken) { @@ -33,28 +35,31 @@ if (localStorage.jwtToken) { // Logout user store.dispatch(logoutUser()); - // Redirect to login - window.location.href = './login'; + // Redirect to NewPage, was login + window.location.href = './'; } } function App () { - return ( + return (
- +
+ - - } - /> - - - - + + } + /> + + + + + +
diff --git a/frontend/src/components/NavBar/NavBar.jsx b/frontend/src/components/NavBar/NavBar.jsx index 5d05e5a..0179f7b 100644 --- a/frontend/src/components/NavBar/NavBar.jsx +++ b/frontend/src/components/NavBar/NavBar.jsx @@ -3,25 +3,35 @@ import { Link, withRouter } from "react-router-dom"; import PropTypes from "prop-types"; import { connect } from "react-redux"; import { logoutUser } from "../../actions/authActions"; +import { MainNav, NavLogo, StyledLinked, Header, NavItemLocation} from "./NavBar.styled"; +import logo from '../../images/real.png'; class NavBar extends Component { render() { const { auth, logoutUser } = this.props; return ( - <> - {auth.isAuthenticated ? ( + + + + +
Cloud Haven
+ <> - -

{`Logged in as: You`}

+ {auth.isAuthenticated ? ( + <> + +

{`Logged in as: You`}

+ + ) : ( + <> + Login + Register + + )} - ) : ( - <> - Login - Register - - )} - +
+
); } } diff --git a/frontend/src/components/NavBar/NavBar.styled.js b/frontend/src/components/NavBar/NavBar.styled.js index 4f210a9..5ab0465 100644 --- a/frontend/src/components/NavBar/NavBar.styled.js +++ b/frontend/src/components/NavBar/NavBar.styled.js @@ -1 +1,57 @@ import styled from 'styled-components'; +import { Link } from "react-router-dom"; + +export const MainNav = styled.a` + align-items: center; + background: gray; + display: flex; + flex-flow: row nowrap; + -webkit-font-smoothing: antialiased; + height: 60px; + padding: 0 30px; + box-shadow: 0 2px 4px 0 rgba(0,0,0,.2); +`; + +export const NavLogo = styled.a` + display: flex; + height: 100%; + margin-right: 10px; + transition: opacity 0.2s ease-in-out; + :hover { + cursor: pointer; + opacity: 0.5; + } + > img { + margin: auto; + } + `; + + export const StyledLinked = styled(Link)` + font-family: 'Trebuchet MS', sans-serif; + color: white; + text-decoration: none; + height: 100%; + padding: 0px 20px; + + :hover { + color: black; + transition: all 0.3s ease; + } + `; + + export const Header = styled.h2` + text-align: center; + color: black; + font-family: 'Trebuchet MS', sans-serif; + :hover { + cursor: pointer; + } +`; + +export const NavItemLocation = styled.div` + display: flex; + flex-flow: row nowrap; + align-items: center; + margin-left: auto; + justify-content: space-between; +`; \ No newline at end of file diff --git a/frontend/src/components/NewPage/NewPage.jsx b/frontend/src/components/NewPage/NewPage.jsx new file mode 100644 index 0000000..8cb60e5 --- /dev/null +++ b/frontend/src/components/NewPage/NewPage.jsx @@ -0,0 +1,50 @@ +import React, { Component } from "react"; + +class NewPage extends Component { + + constructor(props) { + super(props); + this.state = { + students: [ + { id: 1, name: 'Joe', age: 21, email: 'joe@test.com'}, + { id: 2, name: 'Bob', age: 22, email: 'Bob@test.com'} + ] + } + } + + returnTableData() { + return this.state.students.map((student, index) => { + let col = Object.keys(student) + return ( + + {col.map((val, index) => { + return {student[col[index]]} + })} + + ) + }) + } + + renderTableHeader() { + let header = Object.keys(this.state.students[0]) + return header.map((key, index) => { + return {key.toUpperCase()} + }) + } + + render() { + return ( +
+

TESTING TABLE PAGE

+ + + {this.renderTableHeader()} + {this.returnTableData()} + +
+
+ ) + } +} + +export default NewPage; \ No newline at end of file diff --git a/frontend/src/components/NewPage/NewPage.styled.js b/frontend/src/components/NewPage/NewPage.styled.js new file mode 100644 index 0000000..7a75875 --- /dev/null +++ b/frontend/src/components/NewPage/NewPage.styled.js @@ -0,0 +1,2 @@ +import styled from 'styled-components'; + diff --git a/frontend/src/components/NewPage/NewPage.test.js b/frontend/src/components/NewPage/NewPage.test.js new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/images/gray.jpg b/frontend/src/images/gray.jpg new file mode 100644 index 0000000..f31f5ca Binary files /dev/null and b/frontend/src/images/gray.jpg differ diff --git a/frontend/src/images/logo.png b/frontend/src/images/logo.png new file mode 100644 index 0000000..cf923dd Binary files /dev/null and b/frontend/src/images/logo.png differ diff --git a/frontend/src/images/real.png b/frontend/src/images/real.png new file mode 100644 index 0000000..8476805 Binary files /dev/null and b/frontend/src/images/real.png differ diff --git a/frontend/src/images/test.PNG b/frontend/src/images/test.PNG new file mode 100644 index 0000000..78834ab Binary files /dev/null and b/frontend/src/images/test.PNG differ diff --git a/frontend/src/images/testLOGO.jpg b/frontend/src/images/testLOGO.jpg new file mode 100644 index 0000000..0fee250 Binary files /dev/null and b/frontend/src/images/testLOGO.jpg differ diff --git a/frontend/src/pages/Home/Home.jsx b/frontend/src/pages/Home/Home.jsx index 3dfa2d9..1101a33 100644 --- a/frontend/src/pages/Home/Home.jsx +++ b/frontend/src/pages/Home/Home.jsx @@ -1,10 +1,14 @@ import React, { Component } from "react"; -export default class Home extends Component { +export default class EmptyPage extends Component { + constructor(props) { + super(props); + } render() { + return (
- Welcome Home +

Hello

) } diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx deleted file mode 100644 index bd8ec04..0000000 --- a/frontend/src/pages/Login.jsx +++ /dev/null @@ -1,102 +0,0 @@ -import React, { Component } from "react"; -import { Link } from "react-router-dom"; -import PropTypes from "prop-types"; -import { connect } from "react-redux"; -import { loginUser } from "../actions/authActions"; - -class Login extends Component { - constructor() { - super(); - this.state = { - email: "", - password: "", - errors: {}, - }; - } - - componentWillReceiveProps(nextProps) { - if (nextProps.auth.isAuthenticated) { - this.props.history.push("/home"); - } - - if (nextProps.errors) { - this.setState({ - errors: nextProps.errors, - }); - } - } - - onChange = (e) => { - this.setState({ [e.target.id]: e.target.value }); - }; - - onSubmit = (e) => { - e.preventDefault(); - - const userData = { - email: this.state.email, - password: this.state.password, - }; - - this.props.loginUser(userData); - }; - - render() { - const { errors } = this.state; - - return ( -
-

- Login below -

- -
-
- - - - {errors.email} - {errors.emailnotfound} - -
-
- - - - {errors.password} - {errors.passwordincorrect} - -
-
- -
-
-
- ); - } -} - -Login.propTypes = { - loginUser: PropTypes.func.isRequired, - auth: PropTypes.object.isRequired, - errors: PropTypes.object.isRequired, -}; - -const mapStateToProps = (state) => ({ - auth: state.auth, - errors: state.errors, -}); - -export default connect(mapStateToProps, { loginUser })(Login); diff --git a/frontend/src/pages/Login/Login.jsx b/frontend/src/pages/Login/Login.jsx new file mode 100644 index 0000000..06356b1 --- /dev/null +++ b/frontend/src/pages/Login/Login.jsx @@ -0,0 +1,106 @@ +import React, { Component } from "react"; +import { Link } from "react-router-dom"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { loginUser } from "../../actions/authActions"; +import { Button, Input , LoginContainer, LoginWrapper, Label, TextWrapper, MainHeader} from './Login.styled' + +class Login extends Component { + constructor() { + super(); + this.state = { + email: "", + password: "", + errors: {}, + }; + } + + componentWillReceiveProps(nextProps) { + if (nextProps.auth.isAuthenticated) { + this.props.history.push("/home"); + } + + if (nextProps.errors) { + this.setState({ + errors: nextProps.errors, + }); + } + } + + onChange = (e) => { + this.setState({ [e.target.id]: e.target.value }); + }; + + onSubmit = (e) => { + e.preventDefault(); + + const userData = { + email: this.state.email, + password: this.state.password, + }; + + this.props.loginUser(userData); + }; + + render() { + const { errors } = this.state; + + return ( + +
+ + Welcome to Cloud Haven! + + + + +
+
+ + {errors.email} + {errors.emailnotfound} + + +
+
+ + {errors.password} + {errors.passwordincorrect} + + +
+
+ +
+
+
+
+
+ ); + } +} + +Login.propTypes = { + loginUser: PropTypes.func.isRequired, + auth: PropTypes.object.isRequired, + errors: PropTypes.object.isRequired, +}; + +const mapStateToProps = (state) => ({ + auth: state.auth, + errors: state.errors, +}); + +export default connect(mapStateToProps, { loginUser })(Login); diff --git a/frontend/src/pages/Login/Login.styled.js b/frontend/src/pages/Login/Login.styled.js new file mode 100644 index 0000000..22e1b3f --- /dev/null +++ b/frontend/src/pages/Login/Login.styled.js @@ -0,0 +1,103 @@ +import styled from 'styled-components' +import gray from '../../images/gray.jpg'; + +export const MainHeader = styled.h1` + position: absolute; + font-family: 'Trebuchet MS', sans-serif; + text-align: center; + left: 27%; + color: white; + top: 1%; +`; + + +export const TextWrapper = styled.body` + position: absolute; + top: 50%; + left: 35%; + width: 900px; + height: 600px; + padding: 40px; + padding-top: 50px; + box-sizing: border-box; + transform: translate(-50%, -50%); + box-shadow: 0 1px 15px; + color: #FFFFE0; + border-radius: 20px; + +`; + + +export const Button = styled.button` + /* This renders the buttons above... Edit me! */ + display: inline-block; + font-family: 'Trebuchet MS', sans-serif; + border-radius: 20px; //button shape + padding: 8px; + margin: 10px 60px; + width: 150px; + color: black; + border: 2px solid black; + background-color: #A9A9A9; + :hover { + cursor: pointer; + background: #FFFFE0; + transition: 0.2s ease-in-out; + } +`; + +export const Input = styled.input` + display: block; + text-align: left; + font-family: 'Trebuchet MS', sans-serif; + width: 200px; + padding: 10px 10px; //inside padding + margin: 20px auto; + background: transparent; + border: 2px solid #FFFFE0 +; + color: white; + cursor: pointer; + font-size: 15px; + border-radius: 20px; + outline: none; + ::placeholder { + font-family: 'Trebuchet MS', sans-serif; + } + +`; + +export const Label = styled.label` + position: absolute; + top: 5%; + left: 34%; + margin: 0 0 30px; + font-family: 'Trebuchet MS', sans-serif; + color: white; + text-align: center; + font-size: 30px; + font-weight: bold; +`; + + + +export const LoginWrapper = styled.body` + position: absolute; + top: 50%; + left: 80%; + width: 350px; + height: 270px; + padding: 40px; + padding-top: 50px; + box-sizing: border-box; + transform: translate(-50%, -50%); + box-shadow: 0 15px 25px rgba(0,0,0,1); + border-radius: 20px; +`; + +export const LoginContainer = styled.div` + background-image: url(${gray}); + height: 100vh; + background-position: center; + background-size: cover; +`; diff --git a/frontend/src/pages/Login/Login.test.js b/frontend/src/pages/Login/Login.test.js new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/pages/Register.jsx b/frontend/src/pages/Register.jsx deleted file mode 100644 index f5fc20e..0000000 --- a/frontend/src/pages/Register.jsx +++ /dev/null @@ -1,117 +0,0 @@ -import React, { Component } from "react"; -import { Link, withRouter } from "react-router-dom"; -import PropTypes from "prop-types"; -import { connect } from "react-redux"; -import { registerUser } from "../actions/authActions"; - -class Register extends Component { - constructor() { - super(); - this.state = { - name: "", - email: "", - password: "", - password2: "", - errors: {}, - }; - } - - componentWillReceiveProps(nextProps) { - if (nextProps.errors) { - this.setState({ - errors: nextProps.errors, - }); - } - } - - onChange = (e) => { - this.setState({ [e.target.id]: e.target.value }); - }; - - onSubmit = (e) => { - e.preventDefault(); - - const newUser = { - name: this.state.name, - email: this.state.email, - password: this.state.password, - password2: this.state.password2, - }; - - this.props.registerUser(newUser, this.props.history); - }; - - render() { - const { errors } = this.state; - - return ( -
-

- Register below -

-
-
- - - {errors.name} -
-
- - - {errors.email} -
-
- - - {errors.password} -
-
- - - {errors.password2} -
-
- -
-
-
- ); - } -} - -Register.propTypes = { - registerUser: PropTypes.func.isRequired, - auth: PropTypes.object.isRequired, - errors: PropTypes.object.isRequired, -}; - -const mapStateToProps = (state) => ({ - auth: state.auth, - errors: state.errors, -}); - -export default connect(mapStateToProps, { registerUser })(withRouter(Register)); diff --git a/frontend/src/pages/Register/Register.jsx b/frontend/src/pages/Register/Register.jsx new file mode 100644 index 0000000..f4d3649 --- /dev/null +++ b/frontend/src/pages/Register/Register.jsx @@ -0,0 +1,120 @@ +import React, { Component } from "react"; +import { Link, withRouter } from "react-router-dom"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { registerUser } from "../../actions/authActions"; +import { Button, Input , LoginContainer, Wrapper, Label} from './Register.styled' +import Login from "../Login/Login"; + +class Register extends Component { + constructor() { + super(); + this.state = { + name: "", + email: "", + password: "", + password2: "", + errors: {}, + }; + } + + componentWillReceiveProps(nextProps) { + if (nextProps.errors) { + this.setState({ + errors: nextProps.errors, + }); + } + } + + onChange = (e) => { + this.setState({ [e.target.id]: e.target.value }); + }; + + onSubmit = (e) => { + e.preventDefault(); + + const newUser = { + name: this.state.name, + email: this.state.email, + password: this.state.password, + password2: this.state.password2, + }; + + this.props.registerUser(newUser, this.props.history); + }; + + render() { + const { errors } = this.state; + + return ( + + + +
+ + +
+
+ + + {errors.name} +
+
+ + {errors.email} +
+
+ + {errors.password} +
+
+ + {errors.password2} +
+
+ +
+
+
+
+
+ ); + } +} + +Register.propTypes = { + registerUser: PropTypes.func.isRequired, + auth: PropTypes.object.isRequired, + errors: PropTypes.object.isRequired, +}; + +const mapStateToProps = (state) => ({ + auth: state.auth, + errors: state.errors, +}); + +export default connect(mapStateToProps, { registerUser })(withRouter(Register)); diff --git a/frontend/src/pages/Register/Register.styled.js b/frontend/src/pages/Register/Register.styled.js new file mode 100644 index 0000000..a209cf4 --- /dev/null +++ b/frontend/src/pages/Register/Register.styled.js @@ -0,0 +1,77 @@ +import styled from 'styled-components' +import gray from '../../images/gray.jpg'; + + +export const Button = styled.button` + /* This renders the buttons above... Edit me! */ + display: inline-block; + font-family: 'Trebuchet MS', sans-serif; + border-radius: 20px; //button shape + padding: 8px; + margin: 10px 60px; + width: 150px; + color: black; + border: 2px solid black; + background-color: #A9A9A9; + :hover { + cursor: pointer; + background: #FFFFE0; + transition: 0.2s ease-in-out; + } +`; + +export const Input = styled.input` + display: block; + text-align: left; + font-family: 'Trebuchet MS', sans-serif; + width: 200px; + padding: 10px 10px; //inside padding + margin: 20px auto; + background: transparent; + border: 2px solid #FFFFE0 +; + color: white; + cursor: pointer; + font-size: 15px; + border-radius: 20px; + outline: none; + ::placeholder { + font-family: 'Trebuchet MS', sans-serif; + } + +`; + +export const Label = styled.label` + position: absolute; + top: 5%; + left: 34%; + margin: 0 0 30px; + font-family: 'Trebuchet MS', sans-serif; + color: white; + text-align: center; + font-size: 30px; + font-weight: bold; +`; + + + +export const Wrapper = styled.body` + position: absolute; + top: 40%; + left: 50%; + width: 350px; + height: 400px; + padding: 40px; + padding-top: 50px; + box-sizing: border-box; + transform: translate(-50%, -50%); + box-shadow: 0 15px 25px rgba(0,0,0,1); + border-radius: 20px; +`; + +export const LoginContainer = styled.div` + background-image: url(${gray}); + height: 100vh; + background-position: center; + background-size: cover; +`; diff --git a/frontend/src/pages/Register/Register.test.js b/frontend/src/pages/Register/Register.test.js new file mode 100644 index 0000000..e69de29