Commit 31ce42a8 authored by Martin Fahl's avatar Martin Fahl

send increment/decrement to server

parent 905a1445
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
"dependencies": { "dependencies": {
"@material-ui/core": "^1.4.3", "@material-ui/core": "^1.4.3",
"@material-ui/icons": "^2.0.1", "@material-ui/icons": "^2.0.1",
"axios": "^0.18.0",
"enzyme": "^3.3.0", "enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1", "enzyme-adapter-react-16": "^1.1.1",
"react": "^16.4.1", "react": "^16.4.1",
......
import Axios from 'axios';
// actions // actions
export const ITEM_ADDED = 'ITEM_ADDED'; export const ITEM_ADDED = 'ITEM_ADDED';
export const UPDATE_FILTER = 'UPDATE_FILTER'; export const UPDATE_FILTER = 'UPDATE_FILTER';
export const ITEM_DELETED = 'ITEM_DELETED'; export const ITEM_DELETED = 'ITEM_DELETED';
export const INCREMENT = 'INREMENT_ITEM'; export const ITEM_UPDATED = 'ITEM_UPDATED';
export const DECREMENT = 'DECREMENT_ITEM';
export const ITEMS_LOADED = 'ITEMS_LOADED'; export const ITEMS_LOADED = 'ITEMS_LOADED';
export const UPDATE_ADD_DIALOG_NAME = 'UPDATE_ADD_DIALOG_NAME'; export const UPDATE_ADD_DIALOG_NAME = 'UPDATE_ADD_DIALOG_NAME';
export const UPDATE_ADD_DIALOG_QUANTITY = 'UPDATE_ADD_DIALOG_QUANTITY'; export const UPDATE_ADD_DIALOG_QUANTITY = 'UPDATE_ADD_DIALOG_QUANTITY';
...@@ -26,15 +26,12 @@ export const itemDeleted = id => ({ ...@@ -26,15 +26,12 @@ export const itemDeleted = id => ({
type: ITEM_DELETED, type: ITEM_DELETED,
id id
}) })
export const increment = id => ({
type: INCREMENT,
id
})
export const decrement = id => ({ export const itemUpdated = (id, name, quantity) => ({
type: DECREMENT, type: ITEM_UPDATED,
id id,
name,
quantity
}) })
export const openAddDialog = () => ({ export const openAddDialog = () => ({
...@@ -67,9 +64,9 @@ export const getAllItems = () => dispatch => { ...@@ -67,9 +64,9 @@ export const getAllItems = () => dispatch => {
} }
export const addItem = (name, quantity) => dispatch => { export const addItem = (name, quantity) => dispatch => {
var xmlhttp = new XMLHttpRequest(); var xmlhttp = new XMLHttpRequest()
xmlhttp.open("POST", "/api/items"); xmlhttp.open("POST", "/api/items")
xmlhttp.setRequestHeader("Content-Type", "application/json"); xmlhttp.setRequestHeader("Content-Type", "application/json")
xmlhttp.onreadystatechange = () => { xmlhttp.onreadystatechange = () => {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) { if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
var json = JSON.parse(xmlhttp.responseText); var json = JSON.parse(xmlhttp.responseText);
...@@ -80,12 +77,18 @@ export const addItem = (name, quantity) => dispatch => { ...@@ -80,12 +77,18 @@ export const addItem = (name, quantity) => dispatch => {
} }
export const deleteItem = (id) => dispatch => { export const deleteItem = (id) => dispatch => {
var xmlhttp = new XMLHttpRequest(); var xmlhttp = new XMLHttpRequest()
xmlhttp.open("DELETE", "/api/items/"+id); xmlhttp.open("DELETE", "/api/items/"+id)
xmlhttp.onreadystatechange = () => { xmlhttp.onreadystatechange = () => {
if (xmlhttp.readyState === 4 && xmlhttp.status === 204) { if (xmlhttp.readyState === 4 && xmlhttp.status === 204) {
dispatch(itemDeleted(id)) dispatch(itemDeleted(id))
} }
} }
xmlhttp.send() xmlhttp.send()
} }
\ No newline at end of file
export const updateItem = (id, name, quantity) => dispatch => {
dispatch(itemUpdated(id, name, quantity))
Axios.put('/api/items/'+id, {id, name, quantity}).catch(dispatch(getAllItems));
}
...@@ -37,24 +37,6 @@ describe('actions', () => { ...@@ -37,24 +37,6 @@ describe('actions', () => {
}) })
}) })
describe('actions', () => {
it('should create an action to increment an item\'s quantity locally', () => {
const expectedAction = {
type: actions.INCREMENT,
}
expect(actions.increment()).toEqual(expectedAction)
})
})
describe('actions', () => {
it('should create an action to decrement an item\'s quantity locally', () => {
const expectedAction = {
type: actions.DECREMENT,
}
expect(actions.decrement()).toEqual(expectedAction)
})
})
describe('actions', () => { describe('actions', () => {
it('should create an action to open the add dialog', () => { it('should create an action to open the add dialog', () => {
const expectedAction = { const expectedAction = {
...@@ -104,4 +86,19 @@ describe('actions', () => { ...@@ -104,4 +86,19 @@ describe('actions', () => {
} }
expect(actions.itemsLoaded(items)).toEqual(expectedAction) expect(actions.itemsLoaded(items)).toEqual(expectedAction)
}) })
})
describe('actions', () => {
it('should create an action to signal that the items have been updated', () => {
const id = 1
const name = "Hugo"
const quantity = 98
const expectedAction = {
type: actions.ITEM_UPDATED,
id,
name,
quantity
}
expect(actions.itemUpdated(id, name, quantity)).toEqual(expectedAction)
})
}) })
\ No newline at end of file
...@@ -8,14 +8,17 @@ import IconButton from '@material-ui/core/IconButton'; ...@@ -8,14 +8,17 @@ import IconButton from '@material-ui/core/IconButton';
import DeleteIcon from '@material-ui/icons/Delete'; import DeleteIcon from '@material-ui/icons/Delete';
import Avatar from '@material-ui/core/Avatar'; import Avatar from '@material-ui/core/Avatar';
const Item = ({ id, name, quantity, increment, decrement, deleteItem }) => ( const increment = (quantity) => quantity + 1
const decrement = (quantity) => quantity > 1 ? quantity - 1 : 0
const Item = ({ id, name, quantity, updateItem, deleteItem }) => (
<ListItem> <ListItem>
<ListItemText> <ListItemText>
<Typography variant="subheading"> <Typography variant="subheading">
{name} {name}
</Typography> </Typography>
</ListItemText> </ListItemText>
<IconButton onClick={() => decrement(id)} aria-label="Decrement"> <IconButton onClick={() => updateItem(id, name, decrement(quantity))} aria-label="Decrement">
<Icon color="secondary">arrow_downward</Icon> <Icon color="secondary">arrow_downward</Icon>
</IconButton> </IconButton>
...@@ -25,7 +28,7 @@ const Item = ({ id, name, quantity, increment, decrement, deleteItem }) => ( ...@@ -25,7 +28,7 @@ const Item = ({ id, name, quantity, increment, decrement, deleteItem }) => (
</Typography> </Typography>
</Avatar> </Avatar>
<IconButton onClick={() => increment(id)} aria-label="Increment"> <IconButton onClick={() => updateItem(id, name, increment(quantity))} aria-label="Increment">
<Icon color="secondary">arrow_upward</Icon> <Icon color="secondary">arrow_upward</Icon>
</IconButton> </IconButton>
<IconButton onClick={() => deleteItem(id)} aria-label="Delete"> <IconButton onClick={() => deleteItem(id)} aria-label="Delete">
......
import { connect } from 'react-redux' import { connect } from 'react-redux'
import Item from '../../components/Item/Item' import Item from '../../components/Item/Item'
import { increment, decrement, deleteItem } from '../../actions' import { updateItem, deleteItem } from '../../actions'
import { createSelector } from 'reselect' import { createSelector } from 'reselect'
const getItem = (state, props) => state.items.find(item => item.id === props.id) const getItem = (state, props) => state.items.find(item => item.id === props.id)
...@@ -15,8 +15,7 @@ const mapStateToProps = (state, props) => ({ ...@@ -15,8 +15,7 @@ const mapStateToProps = (state, props) => ({
}) })
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
increment: id => dispatch(increment(id)), updateItem: (id, name, quantity) => dispatch(updateItem(id, name, quantity)),
decrement: id => dispatch(decrement(id)),
deleteItem: id => dispatch(deleteItem(id)) deleteItem: id => dispatch(deleteItem(id))
}) })
......
import { ITEM_DELETED, INCREMENT, DECREMENT, ITEMS_LOADED, ITEM_ADDED } from '../actions'; import { ITEM_DELETED, ITEMS_LOADED, ITEM_ADDED, ITEM_UPDATED } from '../actions';
const items = (state = [], action) => { const items = (state = [], action) => {
switch (action.type) { switch (action.type) {
...@@ -15,13 +15,9 @@ const items = (state = [], action) => { ...@@ -15,13 +15,9 @@ const items = (state = [], action) => {
] ]
case ITEM_DELETED: case ITEM_DELETED:
return state.filter(item => (item.id !== action.id)) return state.filter(item => (item.id !== action.id))
case INCREMENT: case ITEM_UPDATED:
return state.map(item => ( return state.map(item => (
item.id === action.id ? {...item, quantity: item.quantity + 1} : item item.id === action.id ? {...item, name: action.name, quantity: action.quantity } : item
));
case DECREMENT:
return state.map(item => (
item.id === action.id ? {...item, quantity: item.quantity > 1 ? item.quantity - 1 : 0} : item
)); ));
default: default:
return state return state
......
...@@ -409,6 +409,13 @@ aws4@^1.6.0: ...@@ -409,6 +409,13 @@ aws4@^1.6.0:
version "1.7.0" version "1.7.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289"
axios@^0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
dependencies:
follow-redirects "^1.3.0"
is-buffer "^1.1.5"
axobject-query@^0.1.0: axobject-query@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-0.1.0.tgz#62f59dbc59c9f9242759ca349960e7a2fe3c36c0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-0.1.0.tgz#62f59dbc59c9f9242759ca349960e7a2fe3c36c0"
...@@ -2971,6 +2978,12 @@ follow-redirects@^1.0.0: ...@@ -2971,6 +2978,12 @@ follow-redirects@^1.0.0:
dependencies: dependencies:
debug "^3.1.0" debug "^3.1.0"
follow-redirects@^1.3.0:
version "1.5.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.2.tgz#5a9d80e0165957e5ef0c1210678fc5c4acb9fb03"
dependencies:
debug "^3.1.0"
for-in@^1.0.1, for-in@^1.0.2: for-in@^1.0.1, for-in@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
......
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