Commit 3bea09ad authored by Martin Fahl's avatar Martin Fahl
Browse files

refactors to more redux use

parent dbc8a837
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
export const ADD = 'ADD_ITEM'; export const ADD = 'ADD_ITEM';
export const UPDATE_FILTER = 'UPDATE_FILTER'; export const UPDATE_FILTER = 'UPDATE_FILTER';
export const DELETE_ITEM = 'DELETE_ITEM'; export const DELETE_ITEM = 'DELETE_ITEM';
export const INCREMENT = 'INREMENT_ITEM';
export const DECREMENT = 'DECREMENT_ITEM';
export const add = (id, name) => ({ export const add = (id, name) => ({
type: ADD, type: ADD,
...@@ -18,4 +20,13 @@ export const deleteItem = id => ({ ...@@ -18,4 +20,13 @@ export const deleteItem = id => ({
type: DELETE_ITEM, type: DELETE_ITEM,
id id
}); });
\ No newline at end of file export const increment = id => ({
type: INCREMENT,
id: id,
});
export const decrement = id => ({
type: DECREMENT,
id: id,
});
\ No newline at end of file
import React from 'react'; import React from 'react';
import { Navbar } from "../Navbar/Navbar"; import { Navbar } from "../Navbar/Navbar";
import { CodecentricFooter } from "../CodecentricFooter/CodecentricFooter"; import { CodecentricFooter } from "../CodecentricFooter/CodecentricFooter";
import InventoryListContainer from '../../container/InventoryList/InventoryListContainer'; import InventoryListContainer from '../../container/InventoryListContainer/InventoryListContainer';
export const App = () => ( const App = () => (
<div className="App"> <div className="App">
<Navbar appName="Inventory" /> <Navbar appName="Inventory" />
...@@ -14,3 +14,4 @@ export const App = () => ( ...@@ -14,3 +14,4 @@ export const App = () => (
</div> </div>
); );
export default App
\ No newline at end of file
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './App';
import renderer from "react-test-renderer";
jest.mock("../../container/InventoryList/InventoryListContainer.js", () => ({
InventoryListContainer: () => <div name="InventoryListContainer" />
}));
jest.mock("../Navbar/Navbar.js", () => ({
Navbar: () => <div name="Navbar" />
}));
describe("App", () => {
it("should render without crashing", () => {
const div = document.createElement("div");
ReactDOM.render(<App />, div);
});
it("should render as expected", () => {
const appContainer = renderer.create(<App />).toJSON();
expect(appContainer).toMatchSnapshot();
});
});
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Item } from "../../container/Item/Item"; import Item from "../../container/ItemContainer/ItemContainer";
import { Filter } from "../Filter/Filter"; import { Filter } from "../Filter/Filter";
import { Container, Row, Col, Card, CardBody, ListGroup } from "mdbreact"; import { Container, Row, Col, Card, CardBody, ListGroup } from "mdbreact";
...@@ -17,7 +17,6 @@ const InventoryList = ({ items, filterTerm, updateFilter, deleteItem }) => ( ...@@ -17,7 +17,6 @@ const InventoryList = ({ items, filterTerm, updateFilter, deleteItem }) => (
<Item <Item
key={item.id} key={item.id}
{...item} {...item}
deleteItem={() => deleteItem(item.id)}
/> />
)} )}
</ListGroup> </ListGroup>
......
...@@ -7,7 +7,7 @@ jest.mock("../Filter/Filter", () => ({ ...@@ -7,7 +7,7 @@ jest.mock("../Filter/Filter", () => ({
Filter: () => <div name="Filter" /> Filter: () => <div name="Filter" />
})); }));
jest.mock("../../container/Item/Item", () => ({ jest.mock("../../container/ItemContainer/ItemContainer", () => ({
Item: () => <div name="Item" /> Item: () => <div name="Item" />
})); }));
......
import React, { Component } from "react";
import PropTypes from "prop-types";
import { ListGroupItem, Badge, Fa } from "mdbreact";
import { Row, Col } from "mdbreact";
const Item = ({ id, name, amount, increment, decrement, deleteItem }) => (
<ListGroupItem>
<Row>
<Col md="6" xs="4">
{name}
</Col>
<Col md="6" xs="8">
<Badge color="secondary" className="ml-1 mr-1" onClick={() => decrement(id)}><Fa icon="minus-square" aria-hidden="true"/></Badge>
<Badge color="default" className="ml-1 mr-1" pill>{amount}</Badge>
<Badge color="secondary" className="ml-1 mr-1" onClick={() => increment(id)}><Fa icon="plus-square" aria-hidden="true"/></Badge>
<Badge color="danger" className="ml-1 mr-1" onClick={() => deleteItem(id)}><Fa icon="trash" aria-hidden="true"/></Badge>
</Col>
</Row>
</ListGroupItem>
)
Item.propTypes = {
name: PropTypes.string.isRequired,
amount: PropTypes.number,
increment: PropTypes.func,
decrement: PropTypes.func,
deleteItem: PropTypes.func
};
export default Item
\ No newline at end of file
...@@ -21,26 +21,24 @@ exports[`Item should render as expected 1`] = ` ...@@ -21,26 +21,24 @@ exports[`Item should render as expected 1`] = `
> >
<i <i
aria-hidden="true" aria-hidden="true"
className="fa fa-plus-square" className="fa fa-minus-square"
/> />
</span> </span>
<span <span
className="badge default badge-default badge-pill ml-1 mr-1" className="badge default badge-default badge-pill ml-1 mr-1"
> />
0
</span>
<span <span
className="badge secondary badge-secondary ml-1 mr-1" className="badge secondary badge-secondary ml-1 mr-1"
onClick={[Function]} onClick={[Function]}
> >
<i <i
aria-hidden="true" aria-hidden="true"
className="fa fa-minus-square" className="fa fa-plus-square"
/> />
</span> </span>
<span <span
className="badge danger badge-danger ml-1 mr-1" className="badge danger badge-danger ml-1 mr-1"
onClick={undefined} onClick={[Function]}
> >
<i <i
aria-hidden="true" aria-hidden="true"
......
...@@ -24,48 +24,3 @@ export default connect( ...@@ -24,48 +24,3 @@ export default connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(InventoryList) )(InventoryList)
// export class InventoryList extends Component {
// constructor(props) {
// super(props);
// this.state = {
// filterTerm: "",
// items: ["Water", "Bread", "Beer"]
// };
// }
// updateFilter = event => {
// this.setState({ filterTerm: event.target.value });
// };
// render() {
// return (
// <Container>
// <Row className="justify-content-md-center justify-content-center mx-auto">
// <Col sm="12" md="8" lg="6">
// <Card className="mt-4 mb-4 mx-auto">
// <CardBody>
// <Filter
// updateFilter={this.updateFilter}
// filterTerm={this.state.filterTerm}
// />
// <ListGroup>
// {this.state.items
// .filter(items => items.includes(this.state.filterTerm))
// .map((name, index) => (
// <Item key={index} name={name} />
// ))}
// </ListGroup>
// </CardBody>
// </Card>
// </Col>
// </Row>
// </Container>
// );
// }
// }
// InventoryList.propTypes = {
// itemList: PropTypes.array
// };
import React, { Component } from "react";
import PropTypes from "prop-types";
import { ListGroupItem, Badge, Fa } from "mdbreact";
import { Row, Col } from "mdbreact";
export class Item extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
}
increment = event => {
this.setState({ counter: this.state.counter + 1 });
};
decrement = event => {
this.setState({
counter:
this.state.counter > 0 ? this.state.counter - 1 : this.state.counter
});
};
render() {
return (
<ListGroupItem>
<Row>
<Col md="6" xs="4">
{this.props.name}
</Col>
<Col md="6" xs="8">
<Badge color="secondary" className="ml-1 mr-1" onClick={this.increment}><Fa icon="plus-square" aria-hidden="true"/></Badge>
<Badge color="default" className="ml-1 mr-1" pill>{this.state.counter}</Badge>
<Badge color="secondary" className="ml-1 mr-1" onClick={this.decrement}><Fa icon="minus-square" aria-hidden="true"/></Badge>
<Badge color="danger" className="ml-1 mr-1" onClick={this.props.deleteItem}><Fa icon="trash" aria-hidden="true"/></Badge>
</Col>
</Row>
</ListGroupItem>
);
}
}
Item.propTypes = {
name: PropTypes.string.isRequired
};
import React from "react";
import { Item } from "./Item";
import renderer from "react-test-renderer";
describe("Item", () => {
it("should render as expected", () => {
const name = "Water";
const emptyCallback = () => {};
const itemComponent = renderer
.create(<Item name={name} />)
.toJSON();
expect(itemComponent).toMatchSnapshot();
});
});
import { connect } from 'react-redux'
import Item from '../../components/Item/Item'
import { increment, decrement, deleteItem } from '../../actions'
const mapStateToProps = (state, ownProps) => ({
amount: state.items.find(item => item.id === ownProps.id).amount
})
const mapDispatchToProps = dispatch => ({
increment: id => dispatch(increment(id)),
decrement: id => dispatch(decrement(id)),
deleteItem: id => dispatch(deleteItem(id))
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(Item)
...@@ -7,7 +7,7 @@ import rootReducer from './reducers' ...@@ -7,7 +7,7 @@ import rootReducer from './reducers'
import 'font-awesome/css/font-awesome.min.css'; import 'font-awesome/css/font-awesome.min.css';
import 'bootstrap/dist/css/bootstrap.min.css'; import 'bootstrap/dist/css/bootstrap.min.css';
import 'mdbreact/dist/css/mdb.css'; import 'mdbreact/dist/css/mdb.css';
import { App } from './components/App/App'; import App from './components/App/App';
import { add } from './actions'; import { add } from './actions';
const store = createStore(rootReducer) const store = createStore(rootReducer)
......
import { ADD, DELETE_ITEM } from '../actions'; import { ADD, DELETE_ITEM, INCREMENT, DECREMENT } from '../actions';
const items = (state = [], action) => { const items = (state = [], action) => {
switch (action.type) { switch (action.type) {
...@@ -12,7 +12,16 @@ const items = (state = [], action) => { ...@@ -12,7 +12,16 @@ const items = (state = [], action) => {
} }
] ]
case DELETE_ITEM: case DELETE_ITEM:
console.log(action.id);
return state.filter(item => (item.id !== action.id)) return state.filter(item => (item.id !== action.id))
case INCREMENT:
return state.map(item => (
item.id === action.id ? {...item, amount: item.amount + 1} : item
));
case DECREMENT:
return state.map(item => (
item.id === action.id ? {...item, amount: item.amount > 1 ? item.amount - 1 : 0} : item
));
default: default:
return state return state
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment