Skip to content

Commit

Permalink
feat(Authentication) Implement Authentication Modal
Browse files Browse the repository at this point in the history
- Implement uniform authentication modal that can accept signup and login components

[starts #165145794]
  • Loading branch information
MandelaK authored and Joshua Moracha committed Apr 11, 2019
1 parent 0394c0c commit b54ed4c
Show file tree
Hide file tree
Showing 12 changed files with 255 additions and 28 deletions.
61 changes: 61 additions & 0 deletions src/components/AuthenticationModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from "react";
import { connect } from "react-redux";
import { Container, Modal } from "react-bootstrap";
import { Component } from "react";
import RegisterForm from "./RegisterForm";
import Login from "./Login";
import { showModal } from "../store/actions/change-form-action";

const mapStateToProps = state => {
const { isRegister, modalShow } = state.modalState;
return {
isRegister,
modalShow
};
};

class ConnectedAuthenticationModal extends Component {
render() {
const { modalShow, dispatch, isRegister } = this.props;
const onHide = () => dispatch(showModal({ modalShow: false }));
let Form;
let headerMessage;
if (isRegister) {
Form = RegisterForm;
headerMessage = (
<h3 className="col-md-10 col-md-offset-5 header-txt">
Join Author's Haven
</h3>
);
} else {
Form = Login;
headerMessage = (
<h3 className="col-md-10 col-md-offset-5 header-txt">Welcome back</h3>
);
}
return (
<Modal
show={modalShow}
onHide={onHide}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
className="authentication-modal"
>
<Modal.Header className="authentication-modal-header" closeButton>
{headerMessage}
</Modal.Header>
<Modal.Body className="authentication-modal-body">
<Container>
<Form />
</Container>
</Modal.Body>
</Modal>
);
}
}

const AuthenticationModal = connect(mapStateToProps)(
ConnectedAuthenticationModal
);
export default AuthenticationModal;
53 changes: 36 additions & 17 deletions src/components/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
import React from 'react';
import { Navbar, Nav } from 'react-bootstrap';
import { NavLink } from 'react-router-dom';
import React from "react";
import { Navbar, Nav } from "react-bootstrap";
import { NavLink } from "react-router-dom";
import AuthenticationModal from './AuthenticationModal';
import store from '../store/store';
import { LOGIN, REGISTER } from '../store/actions/action-types';

const Header = () => (
<Navbar expand="lg" className="navbar-custom">
<NavLink exact to="/" className="brand">
Author&apos;s Haven
</NavLink>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
<NavLink to="/login" className="nav-link">
Login
export class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
modalShow: false,
isRegister: false
};
}

render() {
return (
<Navbar expand="lg" className="navbar-custom">
<NavLink exact to="/" className="brand">
Author&apos;s Haven
</NavLink>
</Nav>
</Navbar.Collapse>
</Navbar>
);
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
<Nav.Item onClick={() => store.dispatch({type: LOGIN})} className="nav-link auth-btn ">
Login
</Nav.Item>
<Nav.Item onClick={() => store.dispatch({type: REGISTER})} className="nav-link auth-btn get-started">
Get Started
</Nav.Item>
</Nav>
</Navbar.Collapse>
<AuthenticationModal/>
</Navbar>
);
}
}
export default Header;
4 changes: 4 additions & 0 deletions src/components/RegisterForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import React from "react";

const RegisterForm = () => <div className="main-container">Register</div>;
export default RegisterForm;
43 changes: 43 additions & 0 deletions src/css/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,46 @@ body {
text-align: right;
padding: 10px;
}

.get-started {
color: #fcc810 !important;
font-family: "Roboto Condensed", sans-serif;
border: 1px solid #fcc810;
border-radius: 3px;
margin-left: 15px;
}

.auth-btn {
cursor: pointer;
}

.authentication-modal{
background:#f0eded !important;
opacity:0.9;
}
.authentication-modal-body{
border:none !important;
}
.authentication-modal-header{
border:none !important;
}

.modal-content {
opacity: 1 !important;
background-color: white;
max-height: 80%;
}

.authentication-modal-header {
text-align: center;
justify-content: center;
}

.header-txt {
font-size: 28px;
font-weight: 500;
}

.modal-dialog {
height: 100%;
}
30 changes: 30 additions & 0 deletions src/middleware/auth-modal-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
REGISTER,
LOGIN
} from "../store/actions/action-types";
import {
showModal
} from '../store/actions/change-form-action';

export function showModalMiddleware({
dispatch
}) {
return function (next) {
return function (action) {
if (action.type === REGISTER) {
dispatch(showModal({
isRegister: true,
modalShow: true
}))
}
if (action.type === LOGIN) {
dispatch(showModal({
isRegister: false,
modalShow: true
}))
}

return next(action);
}
};
}
3 changes: 3 additions & 0 deletions src/store/actions/action-types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const SHOW_MODAL = 'SHOW_MODAL';
export const REGISTER = 'REGISTER';
export const LOGIN = 'LOGIN';
10 changes: 10 additions & 0 deletions src/store/actions/change-form-action.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {
SHOW_MODAL
} from './action-types';

export function showModal(payload) {
return {
type: SHOW_MODAL,
payload
};
}
14 changes: 5 additions & 9 deletions src/store/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
const initialState = {
articles: [],
notifications: [],
followers: [],
}
import { combineReducers } from 'redux'
import modalReducer from './modal-reducer'

function rootReducer(state = initialState, action){

return state;
};
const rootReducer = combineReducers({
modalState: modalReducer,
})

export default rootReducer;
20 changes: 20 additions & 0 deletions src/store/reducers/modal-reducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { SHOW_MODAL } from '../actions/action-types';

const initialState = {
isRegister: false,
modalShow: false
}

function modalReducer(state = initialState, action) {
const payload = action.payload
switch (action.type) {
case (SHOW_MODAL):
return Object.assign({}, state, payload);
default:
break;
}

return state;
};

export default modalReducer
4 changes: 2 additions & 2 deletions src/store/store.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { createStore, applyMiddleware, compose } from "redux";
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
import { showModalMiddleware } from '../middleware/auth-modal-middleware';

const storeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
rootReducer,
storeEnhancers(applyMiddleware(thunk)),
storeEnhancers(applyMiddleware(thunk, showModalMiddleware)),
);


export default store
17 changes: 17 additions & 0 deletions src/tests/components/AuthenticationModal.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import { shallow, mount } from 'enzyme';
import AuthenticationModal from '../../components/AuthenticationModal';


describe('AuthenticationModal', () => {
it('renders one authentication modal', () => {
const component = shallow(<AuthenticationModal/>);
expect(component).toHaveLength(1);

});
it('renders authentication modal', () => {
const component = shallow(<AuthenticationModal debug />);
expect(component.find('div')).toBeDefined();

});
});
24 changes: 24 additions & 0 deletions src/tests/reducers/modal-reducer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import modalReducer from '../../store/reducers/modal-reducer';
import {
showModal
} from '../../store/actions/change-form-action';

test('modalReducers', () => {
let state;
const action = showModal({
modalShow: false
})
state = modalReducer({
isRegister: true,
modalShow: true
}, {
type: 'SHOW_MODAL',
payload: {
modalShow: false
}
});
expect(state).toEqual({
isRegister: true,
modalShow: false
});
});

0 comments on commit b54ed4c

Please sign in to comment.