Created
May 11, 2017 00:56
-
-
Save alexrqs/87a3c950d0ecdc348d8851b824f53366 to your computer and use it in GitHub Desktop.
Very ugly TodoApp with create-react-app redux, classnames and transitions to explain on pioneras developers
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
export function addTodo (todo) { | |
return { | |
type: 'ADD_TODO', | |
payload: todo, | |
} | |
} | |
export function deleteTodo (id) { | |
return { | |
type: 'DELETE_TODO', | |
payload: id, | |
} | |
} | |
export function selectFilter(filter) { | |
return { | |
type: 'SET_FILTER', | |
payload: filter, | |
} | |
} | |
export function toggleComplete(event, id) { | |
return { | |
type: 'TOGGLE_TODO', | |
payload: { | |
status: event.currentTarget.checked ? 'completed' : 'active', | |
id, | |
}, | |
} | |
} |
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, { Component } from 'react' | |
import TodoList from './components/TodoList' | |
import TodoInput from './components/TodoInput' | |
import Filter from './components/Filter' | |
import './App.css' | |
class App extends Component { | |
render() { | |
return ( | |
<div className="App"> | |
<TodoInput /> | |
<TodoList /> | |
<Filter /> | |
</div> | |
) | |
} | |
} | |
export default 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 { connect } from 'react-redux' | |
import * as actions from '../actions' | |
const Filters = (props) => ( | |
<div> | |
<label> | |
<input | |
onChange={(event) => {props.selectFilter(event.currentTarget.value)}} | |
type="radio" | |
name="filters" | |
value="all" | |
defaultChecked={true} | |
/> | |
All | |
</label> | |
<label> | |
<input | |
onChange={(event) => {props.selectFilter(event.currentTarget.value)}} | |
type="radio" | |
name="filters" | |
value="completed" | |
/> | |
Completed | |
</label> | |
<label> | |
<input | |
onChange={(event) => {props.selectFilter(event.currentTarget.value)}} | |
type="radio" | |
name="filters" | |
value="active" | |
/> | |
Active | |
</label> | |
</div> | |
) | |
export default connect(null, { | |
selectFilter: actions.selectFilter, | |
})(Filters) |
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 { connect } from 'react-redux' | |
import * as actions from '../actions' | |
const TodoInput = props => { | |
let input | |
return ( | |
<form> | |
<input | |
type="text" | |
placeholder="Insert TODO" | |
ref={ node => { input = node }} | |
/> | |
<button type="submit" onClick={(event) => { | |
event.preventDefault() | |
props.addTodo({ | |
task: input.value, | |
state: 'active', | |
}) | |
input.value = "" | |
}}>add</button> | |
</form> | |
) | |
} | |
export default connect(null, { | |
addTodo: actions.addTodo, | |
})(TodoInput) |
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 * as actions from '../actions' | |
import cx from 'classnames' | |
import CSSTransition from 'react-transition-group/CSSTransitionGroup' | |
import './TodoList.css' | |
const TodoList = ({ | |
todos, | |
filter, | |
toggleComplete, | |
deleteTodo, | |
}) => { | |
const visibleTodos = getVisibleTodos(todos, filter) | |
return ( | |
<CSSTransition | |
component="ul" | |
transitionName="addTodo" | |
transitionEnterTimeout={300} | |
transitionLeaveTimeout={300} | |
> | |
{visibleTodos.map((todo, index) => { | |
const isCompleted = todo.state === 'completed' | |
const itemcx = cx('TodoList__item', { | |
completed: isCompleted | |
}) | |
return ( | |
<li key={index} className={itemcx} > | |
<input | |
type="checkbox" | |
checked={isCompleted} | |
onChange={event => { toggleComplete(event, index) } } | |
/> | |
{todo.task} | |
<button onClick={() => { deleteTodo(index) }}>Delete</button> | |
</li> | |
)} | |
)} | |
</CSSTransition> | |
) | |
} | |
TodoList.propTypes = { | |
todos: PropTypes.arrayOf(PropTypes.shape({ | |
state: PropTypes.string.isRequired, | |
})), | |
filter: PropTypes.string, | |
toggleComplete: PropTypes.func, | |
deleteTodo: PropTypes.func, | |
} | |
function getVisibleTodos(todos, filter) { | |
switch (filter) { | |
case "all": | |
return todos | |
case "completed": | |
return todos.filter(todo => todo.state === 'completed') | |
case "active": | |
return todos.filter(todo => todo.state !== 'completed') | |
default: | |
return todos | |
} | |
} | |
const mapStateToProps = ({ todos, filter }) => ({ todos, filter }) | |
export default connect(mapStateToProps, { | |
toggleComplete: actions.toggleComplete, | |
deleteTodo: actions.deleteTodo, | |
})(TodoList) |
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 ReactDOM from 'react-dom' | |
import { Provider } from 'react-redux' | |
import store from './store' | |
import App from './App' | |
import './index.css' | |
store.subscribe(() => { | |
const state = store.getState() | |
console.log('%cstate', 'background: deeppink', state) | |
}) | |
ReactDOM.render( | |
<Provider store={store}> | |
<App /> | |
</Provider> | |
, | |
document.getElementById('root') | |
) |
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
const addTodo = (state = 'all', action) => { | |
if ( action.type === 'SET_FILTER') { | |
return action.payload | |
} | |
return state | |
} | |
export default addTodo |
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 { combineReducers } from 'redux' | |
import todoReducer from './todoReducer' | |
import filterReducer from './filterReducer' | |
const todoApp = combineReducers({ | |
todos: todoReducer, | |
filter: filterReducer, | |
}) | |
export default todoApp |
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
const addTodo = (state = [], action) => { | |
if (action.type === 'ADD_TODO') { | |
return state.concat(action.payload) | |
} | |
if (action.type === 'TOGGLE_TODO') { | |
const id = action.payload.id | |
const todo = state.splice(id, 1) | |
todo[0].state = action.payload.status | |
const todos = [].concat(state.slice(0, id), todo, state.slice(id)) | |
return todos | |
} | |
if (action.type === 'DELETE_TODO') { | |
const id = action.payload | |
const todos = [].concat(state.slice(0, id), state.slice(id + 1)) | |
return todos | |
} | |
return state | |
} | |
export default addTodo |
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 { createStore } from 'redux' | |
import reducers from './reducers' | |
const store = createStore(reducers, { | |
todos: [], | |
filter: 'all', | |
}) | |
export default store |
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
.TodoList__item { | |
text-decoration: none; | |
} | |
.TodoList__item.completed { | |
background-color: crimson; | |
text-decoration: line-through; | |
} | |
/* Animation */ | |
.addTodo-enter { | |
opacity: 0.01; | |
} | |
.addTodo-enter.addTodo-enter-active { | |
opacity: 1; | |
transition: opacity 300ms ease-in; | |
} | |
.addTodo-leave { | |
opacity: 1; | |
} | |
.addTodo-leave.addTodo-leave-active { | |
opacity: 0.01; | |
transition: opacity 300ms ease-in; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment