TODO App wtih React (Advanced UI)

TODO app using Redux and React

by Pratik Bhattachary

HTML

<!DOCTYPE html>
<html>
  <meta name="description" content="TODO App using Redux">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>TODO Redux</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.0/redux.js" type="text/javascript"></script>
  <script src="https://fb.me/react-0.14.3.js"></script>
  <script src="https://fb.me/react-dom-0.14.3.js"></script>
  <script src="https://unpkg.com/expect@%3C21/umd/expect.min.js"></script>

  <body>
    <div id="root"></div>

  </body>

</html>

Babel + JSX

const todo = (state, action) => {
	switch(action.type) {
		case 'ADD_TODO': return {
			id: action.id,
			text: action.text,
			completed: false
		}
		case 'TOGGLE_TODO': 
			if (state.id === action.id)
				return Object.assign({}, state, { completed: !state.completed });
			return state;
		default: return state;
	}
};

const todos = (state = [], action) => {
	switch(action.type) {
		case 'ADD_TODO': 
			return [
				...state,
				todo(undefined, action)
			];
		case 'TOGGLE_TODO': {
			return state.map(t => todo(t, action));
		}
		default:
			return state;
	}
};

const visibilityFilter = (
	state = 'SHOW_ALL',
	action
) => {
	switch(action.type) {
		case 'SET_VISIBILITY_FILTER':
			return action.filter;
		default:
			return state;
	}
}

const { combineReducers } = Redux;
const { createStore } = Redux;
const { Component } = React;

const todoApp = combineReducers({
	todos, visibilityFilter
});

const store = createStore(todoApp);

const getVisibleTodos = (
	todos,
  filter
) => {
	switch (filter) {
  	case 'SHOW_ALL':
    	return todos;
    case 'SHOW_COMPLETED':
    	return todos.filter(t => t.completed)
    case 'SHOW_ACTIVE':
    	return todos.filter(t => !t.completed)
    default:
    	return todos;
  }
}

//Presentational component - No behavior is documented here, its only presentation, i.e. how to render a todo completed
const AddTodo = ({
	onAddClick
}) => {
	let input;
	return (
  <div>
    <input ref={node => {
      	input = node;
      }} />
  	  <button onClick={() => {
      	onAddClick(input.value);
        input.value = '';
      }}>
        Add Todo
      </button>
  </div>
  )
} 

const TodoList = ({
	todos,
  onTodoClick
}) => (
	<ul>
	  {todos.map(todo => 
    	<Todo
    	  key = {todo.id}
    	  {...todo}  //Spreads over the properties of todo object, we can also pass each attribute explicitly
        onClick={() => onTodoClick(todo.id)}
        />
    )}
	</ul>
);

const Todo = ({
	onClick,
  completed,
  text
}) => (
			<li 
             ...