Commit f4fa1d80 authored by Martin Fahl's avatar Martin Fahl

refactors to use default exports everywhere + introduces an add dialog (no functionality yet)

parent ad3ac60b
......@@ -5,11 +5,14 @@ export const DELETE_ITEM = 'DELETE_ITEM';
export const INCREMENT = 'INREMENT_ITEM';
export const DECREMENT = 'DECREMENT_ITEM';
export const ITEMS_LOADED = 'ITEMS_LOADED';
export const OPEN_ADD_DIALOG = 'OPEN_ADD_DIALOG';
export const CLOSE_ADD_DIALOG = 'CLOSE_ADD_DIALOG';
export const add = (id, name) => ({
export const add = (id, name, quantity) => ({
type: ADD,
id,
name: name
name: name,
quantity
})
export const updateFilter = filterTerm => ({
......@@ -32,6 +35,14 @@ export const decrement = id => ({
id
})
export const openAddDialog = () => ({
type: OPEN_ADD_DIALOG
})
export const closeAddDialog = () => ({
type: CLOSE_ADD_DIALOG
})
export const itemsLoaded = (items) => ({
type: ITEMS_LOADED,
items
......
import React from "react";
import PropTypes from "prop-types";
import {Button, TextField, Dialog, DialogActions, DialogContent, DialogTitle, Grid } from '@material-ui/core/';
const AddDialog = ({ isOpen, handleClose, handleCancel, handleAdd }) => (
<Dialog
open={isOpen}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">Add Item to Inventory</DialogTitle>
<DialogContent>
<form>
<Grid container spacing={8} alignItems="flex-end">
<Grid item>
<TextField
autoFocus
margin="normal"
id="name"
label="Name"
type="string"
/>
</Grid>
<Grid item>
<TextField
margin="normal"
id="quantity"
label="Quantity"
type="number"
/>
</Grid>
</Grid>
</form>
</DialogContent>
<DialogActions>
<Button onClick={() => handleCancel()} color="primary">
Cancel
</Button>
<Button onClick={() => handleAdd()} color="primary">
Add
</Button>
</DialogActions>
</Dialog>
)
AddDialog.propTypes = {
isOpen: PropTypes.bool.isRequired,
handleClose: PropTypes.func.isRequired,
handleCancel: PropTypes.func.isRequired,
handleAdd: PropTypes.func.isRequired
};
export default AddDialog
\ No newline at end of file
import React from "react";
const AddDialog = () => <div name="AddDialog" />
export default AddDialog
\ No newline at end of file
import React from 'react';
import { Navbar } from "../Navbar/Navbar";
import { CodecentricFooter } from "../CodecentricFooter/CodecentricFooter";
import Navbar from "../Navbar/Navbar";
import CodecentricFooter from "../CodecentricFooter/CodecentricFooter";
import InventoryListContainer from '../../container/InventoryListContainer/InventoryListContainer';
import { withStyles } from '@material-ui/core/styles'
......
......@@ -2,10 +2,10 @@ import React from 'react';
import PropTypes from "prop-types";
import { Typography, Grid} from '@material-ui/core';
export const CodecentricFooter = ({author, link}) => (
const CodecentricFooter = ({author, link}) => (
<Grid container justify="center">
<Grid item>
<Typography>
<Typography color="inherit" variant="caption">
Created with <span role="img" aria-label="Heart">❤️</span> in {(new Date().getFullYear())} by <a href={link} target="_blank" rel="noopener noreferrer"> {author} </a>
</Typography>
</Grid>
......@@ -16,4 +16,5 @@ CodecentricFooter.propTypes = {
author: PropTypes.string,
link: PropTypes.string
};
\ No newline at end of file
export default CodecentricFooter
\ No newline at end of file
import React from "react";
import { CodecentricFooter } from "./CodecentricFooter";
import CodecentricFooter from "./CodecentricFooter";
import renderer from "react-test-renderer";
describe("CodecentricFooter", () => {
......
......@@ -7,8 +7,8 @@ exports[`CodecentricFooter should render as expected 1`] = `
<div
className="MuiGrid-item-2"
>
<p
className="MuiTypography-root-98 MuiTypography-body1-107"
<span
className="MuiTypography-root-98 MuiTypography-caption-108 MuiTypography-colorInherit-117"
>
Created with
<span
......@@ -29,7 +29,7 @@ exports[`CodecentricFooter should render as expected 1`] = `
Test
</a>
</p>
</span>
</div>
</div>
`;
import React from 'react';
import logo from '../../images/CC_RGB_onBlack.png'; // Tell Webpack this JS file uses this image
export const CodecentricLogo = () => (
const CodecentricLogo = () => (
<img src={logo} height="60" alt="codecentric" />
);
\ No newline at end of file
);
export default CodecentricLogo
\ No newline at end of file
......@@ -4,7 +4,7 @@ import TextField from '@material-ui/core/TextField';
import Icon from '@material-ui/core/Icon';
import InputAdornment from '@material-ui/core/InputAdornment';
export const Filter = ({ filterTerm, updateFilter }) => (
const Filter = ({ filterTerm, updateFilter }) => (
<TextField
id="input-with-icon-textfield"
value={filterTerm}
......@@ -26,3 +26,5 @@ Filter.propTypes = {
filterTerm: PropTypes.string,
updateFilter: PropTypes.func
};
export default Filter
\ No newline at end of file
import React from "react";
import { Filter } from "./Filter";
import Filter from "./Filter";
import renderer from "react-test-renderer";
import { shallow } from "enzyme";
......
import React from "react";
export const Filter = () => <div name="Filter" />
const Filter = () => <div name="Filter" />
export default Filter
\ No newline at end of file
import React, { Fragment } from 'react'
import PropTypes from 'prop-types'
import Item from "../../container/ItemContainer/ItemContainer";
import { Filter } from "../Filter/Filter";
import Filter from "../Filter/Filter";
import { CSSTransitionGroup } from 'react-transition-group' // ES6
import '../../css/animations.css'
import Paper from '@material-ui/core/Paper';
import Grid from '@material-ui/core/Grid';
import List from '@material-ui/core/List';
import { Paper, Grid, List, Button, Icon } from '@material-ui/core/';
import AddDialogContainer from "../../container/AddDialogContainer/AddDialogContainer";
const InventoryList = ({ items, filterTerm, updateFilter, deleteItem }) => (
const InventoryList = ({ items, filterTerm, updateFilter, openAddDialog }) => (
<Fragment>
<Grid container justify="center">
<Grid item sm={12} md={8} lg={6}>
<Paper className="mt-4 mb-4 mx-auto" elevation={1}>
<Filter filterTerm={filterTerm} updateFilter={updateFilter} />
<AddDialogContainer />
<List>
<CSSTransitionGroup
transitionName="example"
......@@ -29,6 +29,9 @@ const InventoryList = ({ items, filterTerm, updateFilter, deleteItem }) => (
)}
</CSSTransitionGroup>
</List>
<Button onClick={openAddDialog} variant="fab" color="secondary" aria-label="Add">
<Icon>add</Icon>
</Button>
</Paper>
</Grid>
</Grid>
......@@ -37,7 +40,7 @@ const InventoryList = ({ items, filterTerm, updateFilter, deleteItem }) => (
InventoryList.propTypes = {
items: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
quantity: PropTypes.number.isRequired
}).isRequired).isRequired,
......
......@@ -4,11 +4,12 @@ import renderer from "react-test-renderer";
jest.mock('../Filter/Filter')
jest.mock('../../container/ItemContainer/ItemContainer')
jest.mock('../../container/AddDialogContainer/AddDialogContainer')
describe("InventoryList", () => {
it("should render as expected", () => {
const itemList = [{
id: 2,
id: "2",
name: "test",
quantity: 1}];
const inventoryListComponent = renderer
......
......@@ -18,6 +18,38 @@ exports[`InventoryList should render as expected 1`] = `
>
<span />
</ul>
<button
aria-label="Add"
className="MuiButtonBase-root-153 MuiButton-root-129 MuiButton-fab-144 MuiButton-contained-138 MuiButton-containedSecondary-140 MuiButton-raised-141 MuiButton-raisedSecondary-143"
disabled={false}
onBlur={[Function]}
onClick={undefined}
onFocus={[Function]}
onKeyDown={[Function]}
onKeyUp={[Function]}
onMouseDown={[Function]}
onMouseLeave={[Function]}
onMouseUp={[Function]}
onTouchEnd={[Function]}
onTouchMove={[Function]}
onTouchStart={[Function]}
tabIndex="0"
type="button"
>
<span
className="MuiButton-label-130"
>
<span
aria-hidden="true"
className="material-icons MuiIcon-root-156"
>
add
</span>
</span>
<span
className="MuiTouchRipple-root-163"
/>
</button>
</div>
</div>
</div>
......
......@@ -6,21 +6,27 @@ import Typography from '@material-ui/core/Typography';
import Icon from '@material-ui/core/Icon';
import IconButton from '@material-ui/core/IconButton';
import DeleteIcon from '@material-ui/icons/Delete';
import Avatar from '@material-ui/core/Avatar';
const Item = ({ id, name, quantity, increment, decrement, deleteItem }) => (
<ListItem>
<ListItemText>
{name}
<Typography variant="subheading">
{name}
</Typography>
</ListItemText>
<IconButton onClick={() => decrement(id)} aria-label="Decrement">
<Icon>arrow_downward</Icon>
<IconButton onClick={() => decrement(id)} aria-label="Decrement">
<Icon color="secondary">arrow_downward</Icon>
</IconButton>
<Typography>
{quantity}
</Typography>
<Avatar >
<Typography variant="subheading">
{quantity}
</Typography>
</Avatar>
<IconButton onClick={() => increment(id)} aria-label="Increment">
<Icon>arrow_upward</Icon>
<Icon color="secondary">arrow_upward</Icon>
</IconButton>
<IconButton onClick={() => deleteItem(id)} aria-label="Delete">
<DeleteIcon />
......@@ -28,21 +34,6 @@ const Item = ({ id, name, quantity, increment, decrement, deleteItem }) => (
</ListItem>
)
/* <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>{quantity}</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> */
Item.propTypes = {
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
......
import React from "react";
export const Item = () => <div name="Item" />
const Item = () => <div name="Item" />
export default Item
\ No newline at end of file
import React from 'react';
import PropTypes from "prop-types";
import { CodecentricLogo } from "../CodecentricLogo/CodecentricLogo";
import CodecentricLogo from "../CodecentricLogo/CodecentricLogo";
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
export const Navbar = ({appName}) => (
const Navbar = ({appName}) => (
<AppBar position="static" color="primary">
<Toolbar>
<CodecentricLogo />
......@@ -20,4 +20,5 @@ export const Navbar = ({appName}) => (
Navbar.propTypes = {
appName: PropTypes.string
};
\ No newline at end of file
export default Navbar
\ No newline at end of file
import React from "react";
import { Navbar } from "./Navbar";
import Navbar from "./Navbar";
import renderer from "react-test-renderer";
import { shallow } from "enzyme";
......
import { connect } from 'react-redux'
import AddDialog from '../../components/AddDialog/AddDialog'
import { createSelector } from 'reselect'
import { closeAddDialog } from '../../actions'
const getAddDialog = state => state.addDialog;
const getIsOpen = createSelector(
[getAddDialog],
(addDialog) => {
return addDialog.isOpen
}
)
const mapStateToProps = state => ({
isOpen: getIsOpen(state)
})
const mapDispatchToProps = dispatch => ({
handleClose: () => dispatch(closeAddDialog()),
handleCancel: () => dispatch(closeAddDialog()),
handleAdd: () => dispatch(closeAddDialog())
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(AddDialog)
import React, { Component } from 'react'
import { connect } from 'react-redux'
import InventoryList from '../../components/InventoryList/InventoryList'
import { updateFilter, deleteItem, getAllItems } from '../../actions'
import { updateFilter, getAllItems, openAddDialog } from '../../actions'
import { createSelector } from 'reselect'
class InventoryListContainer extends Component {
......@@ -36,8 +36,8 @@ const mapStateToProps = state => ({
const mapDispatchToProps = dispatch => ({
updateFilter: event => dispatch(updateFilter(event.target.value)),
deleteItem: id => dispatch(deleteItem(id)),
getAllItems: () => dispatch(getAllItems())
getAllItems: () => dispatch(getAllItems()),
openAddDialog: () => dispatch(openAddDialog())
})
export default connect(
......
import { OPEN_ADD_DIALOG, CLOSE_ADD_DIALOG } from '../actions'
const addDialog = (state = {isOpen: false}, action) => {
switch (action.type) {
case OPEN_ADD_DIALOG:
return {isOpen: true}
case CLOSE_ADD_DIALOG:
return {isOpen: false}
default:
return state
}
}
export default addDialog
import { combineReducers } from 'redux'
import items from './items'
import filterTerm from './filterTerm'
import addDialog from './addDialog'
export default combineReducers({
items,
filterTerm
filterTerm,
addDialog
})
......@@ -10,7 +10,7 @@ const items = (state = [], action) => {
{
id: action.id,
name: action.name,
quantity: 0
quantity: action.quantity
}
]
case DELETE_ITEM:
......
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