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

refactors to more redux use

parent dbc8a837
......@@ -2,6 +2,8 @@
export const ADD = 'ADD_ITEM';
export const UPDATE_FILTER = 'UPDATE_FILTER';
export const DELETE_ITEM = 'DELETE_ITEM';
export const INCREMENT = 'INREMENT_ITEM';
export const DECREMENT = 'DECREMENT_ITEM';
export const add = (id, name) => ({
type: ADD,
......@@ -18,4 +20,13 @@ export const deleteItem = id => ({
type: DELETE_ITEM,
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 { Navbar } from "../Navbar/Navbar";
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">
<Navbar appName="Inventory" />
......@@ -14,3 +14,4 @@ export const App = () => (
</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 PropTypes from 'prop-types'
import { Item } from "../../container/Item/Item";
import Item from "../../container/ItemContainer/ItemContainer";
import { Filter } from "../Filter/Filter";
import { Container, Row, Col, Card, CardBody, ListGroup } from "mdbreact";
......@@ -17,7 +17,6 @@ const InventoryList = ({ items, filterTerm, updateFilter, deleteItem }) => (
<Item
key={item.id}
{...item}
deleteItem={() => deleteItem(item.id)}
/>
)}
</ListGroup>
......
......@@ -7,7 +7,7 @@ jest.mock("../Filter/Filter", () => ({
Filter: () => <div name="Filter" />
}));
jest.mock("../../container/Item/Item", () => ({
jest.mock("../../container/ItemContainer/ItemContainer", () => ({
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`] = `
>
<i
aria-hidden="true"
className="fa fa-plus-square"
className="fa fa-minus-square"
/>
</span>
<span
className="badge default badge-default badge-pill ml-1 mr-1"
>
0
</span>
/>
<span
className="badge secondary badge-secondary ml-1 mr-1"
onClick={[Function]}
>
<i
aria-hidden="true"
className="fa fa-minus-square"
className="fa fa-plus-square"
/>
</span>
<span
className="badge danger badge-danger ml-1 mr-1"
onClick={undefined}
onClick={[Function]}
>
<i
aria-hidden="true"
......
......@@ -24,48 +24,3 @@ export default connect(
mapStateToProps,
mapDispatchToProps
)(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'
import 'font-awesome/css/font-awesome.min.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'mdbreact/dist/css/mdb.css';
import { App } from './components/App/App';
import App from './components/App/App';
import { add } from './actions';
const store = createStore(rootReducer)
......
import { ADD, DELETE_ITEM } from '../actions';
import { ADD, DELETE_ITEM, INCREMENT, DECREMENT } from '../actions';
const items = (state = [], action) => {
switch (action.type) {
......@@ -12,7 +12,16 @@ const items = (state = [], action) => {
}
]
case DELETE_ITEM:
console.log(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:
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