Created
June 30, 2017 18:38
-
-
Save MatthewDailey/afc6f6c7c177c0a563cf6e25284b2d92 to your computer and use it in GitHub Desktop.
VoiceOps Todo App
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import PropTypes from 'prop-types'; | |
import { connect } from 'react-redux'; | |
import { TextField } from 'material-ui'; | |
import { Title, Content, ContentBold } from './components/Text'; | |
import ContainerWithNav from './components/ContainerWithNav'; | |
import { Button } from './components/Buttons'; | |
import { addTodo, removeTodo } from './reducers/TodoReducer'; | |
class Todo extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
isEditing: true, | |
edittingValue: props.todoString, | |
}; | |
} | |
render() { | |
const { todoId, todoString, deleteTodo } = this.props; | |
if (this.state.isEditing) { | |
const saveTodoInput = edittingValue => this.setState({ edittingValue }); | |
return ( | |
<div> | |
<TextField value={this.state.edittingValue} /> | |
<Button | |
label="Save" | |
onPress={() => deleteTodo(todoId)} | |
onChange={(event, newInput) => saveTodoInput(newInput)} | |
/> | |
</div> | |
); | |
} | |
return ( | |
<div> | |
<Content>{todoString}</Content> | |
<Button label="Delete" onPress={() => deleteTodo(todoId)} /> | |
<Button label="Edit" onPress={() => deleteTodo(todoId)} /> | |
</div> | |
); | |
} | |
} | |
Todo.propTypes = { | |
todoId: PropTypes.string.isRequired, | |
todoString: PropTypes.string.isRequired, | |
deleteTodo: PropTypes.func.isRequired, | |
}; | |
const ConnectedTodo = connect(undefined, (dispatch) => ({ | |
deleteTodo: todoId => dispatch(removeTodo(todoId)), | |
}))(Todo); | |
class TodoView extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
todoInput: '', | |
}; | |
} | |
render() { | |
const { todos, saveTodo, deleteTodo } = this.props; | |
const saveTodoInput = todoInput => this.setState({ todoInput }); | |
const addTodoToList = () => { | |
saveTodo(this.state.todoInput); | |
this.setState({ todoInput: '' }); | |
}; | |
return ( | |
<ContainerWithNav> | |
<Title> | |
Hello TODO | |
</Title> | |
{ | |
Object.keys(todos.idToTodo).map(todoId => | |
<ConnectedTodo key={todoId} todoId={todoId} todoString={todos.idToTodo[todoId].todoString} />) | |
} | |
<TextField value={this.state.todoInput} onChange={(event, newValue) => saveTodoInput(newValue)} /> | |
<Button label="Add Todo" onPress={addTodoToList} /> | |
</ContainerWithNav> | |
); | |
} | |
} | |
TodoView.propTypes = { | |
todos: PropTypes.shape({}).isRequired, | |
saveTodo: PropTypes.func.isRequired, | |
}; | |
const mapStateToProps = ({ todos }) => ({ todos }); | |
const mapDispatchToProps = dispatch => ({ | |
saveTodo: todoString => dispatch(addTodo(todoString)), | |
}); | |
export default connect(mapStateToProps, mapDispatchToProps)(TodoView); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import _ from 'lodash-uuid'; | |
import { getActionType } from '@mjd/reducer-utils'; | |
const ADD = 'add-todo'; | |
const REMOVE = 'remove-todo'; | |
const EDIT = 'edit-todo'; | |
const defaultState = { | |
idToTodo: {}, | |
}; | |
export default function TodoReducer(priorState = defaultState, action) { | |
switch (getActionType(action)) { | |
case ADD: | |
return { | |
idToTodo: { | |
[action.id]: { | |
todoString: action.todoString, | |
}, | |
...priorState.idToTodo, | |
}, | |
}; | |
case REMOVE: | |
const newIdToTodo = { | |
...priorState.idToTodo, | |
}; | |
delete newIdToTodo[action.id]; | |
return { | |
idToTodo: newIdToTodo, | |
}; | |
default: | |
return priorState; | |
} | |
} | |
export function addTodo(todoString, id = _.uuid()) { | |
return { | |
type: ADD, | |
todoString, | |
id, | |
}; | |
} | |
export function removeTodo(id) { | |
return { | |
type: REMOVE, | |
id, | |
}; | |
} | |
export function editTodo() { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import TodoReducer, { addTodo, removeTodo } from '../../src/reducers/TodoReducer'; | |
describe('TodoReducer', () => { | |
it('add action has id', () => { | |
expect(addTodo('some string').id).to.exist(); | |
}); | |
it('can add a todo', () => { | |
const initialState = TodoReducer(); | |
expect(Object.keys(initialState.idToTodo)).to.eql([]); | |
const todoString = 'some todo'; | |
const secondState = TodoReducer(initialState, addTodo(todoString)); | |
expect(Object.keys(secondState.idToTodo).length).to.equal(1); | |
const todoId = Object.keys(secondState.idToTodo)[0]; | |
expect(secondState.idToTodo[todoId].todoString).to.equal(todoString); | |
}); | |
it('can remove a todo', () => { | |
const initialState = TodoReducer(); | |
const todoString = 'some todo'; | |
const secondState = TodoReducer(initialState, addTodo(todoString)); | |
const todoId = Object.keys(secondState.idToTodo)[0]; | |
expect(todoId).to.exist(); | |
const stateAfterDelete = TodoReducer(secondState, removeTodo(todoId)); | |
expect(Object.keys(stateAfterDelete.idToTodo)).to.eql([]); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment