Skip to content

Instantly share code, notes, and snippets.

@tak1827
Created September 9, 2018 04:07
Show Gist options
  • Save tak1827/9a901a30fc7dfa7e39c068fc19efc2a4 to your computer and use it in GitHub Desktop.
Save tak1827/9a901a30fc7dfa7e39c068fc19efc2a4 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0">
<title>IPFS TodoApp</title>
<!-- CSS -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
</head>
<body>
<!-- Todo Container -->
<div class="container">
<div class="card">
<div class="card-image">
<img src="https://ipfs.io/ipfs/QmahhVnsP7eRA5MTrE3fQeV8eY8aKmCuUydXP6LuFjLqfs">
<span class="card-title">Todo App hosted by IPFS</span>
</div>
<!-- Card Content -->
<div class="card-content">
<form class="col s12">
<p>Please input your todo</p>
<div class="row">
<div class="input-field col s11">
<input id="new-todo" type="text">
</div>
<div class="col s1">
<a id="add-btn" class="btn-floating btn-large waves-effect waves-light"><i class="material-icons">add</i></a>
</div>
</div>
</form>
<ul id="todo-list" class="collection with-header">
<!-- <li class="collection-item">
<input type="checkbox" id="todo0">
<label for="todo0">Buy Materialize Admin Theme.</label>
</li> -->
</ul>
<div>
<input type="radio" name="visibility" id="show-all" value="all" checked/>
<label id="show-all-label" for="show-all" style="margin-right:32px">Show All</label>
<input type="radio" name="visibility" id="show-active" value="active"/>
<label id="show-active-label" for="show-active" style="margin-right:32px">Show Active</label>
<input type="radio" name="visibility" id="show-completed" value="completed"/>
<label id="show-completed-label" for="show-completed" style="margin-right:32px">Show Completed</label>
</div>
</div>
<!-- Card Content -->
</div>
</div>
<!-- Todo Container -->
</body>
<script>
/***************************
Redux CreateStore
***************************/
const createStore = reducer => {
let state;
const subscribers = [];
const store = {
dispatch: action => {
state = reducer(state, action);
subscribers.forEach(handler => handler());
},
getState: () => state,
subscribe: handler => {
subscribers.push(handler);
}
};
return store;
}
/***************************
Redux CombineReducers
***************************/
const combineReducers = (reducers) => {
return (state = {}, action) => {
return Object.keys(reducers).reduce(
(nextState, key) => {
nextState[key] = reducers[key] (
state[key],
action
)
return nextState;
},
{}
)
}
}
/***************************
Define reducers
***************************/
const CREATE_NOTE = 'CREATE_NOTE';
const TOGGLE_TODO = 'TOGGLE_TODO';
// Todo reducer
const todosReducer = (state = [], action) => {
switch (action.type) {
case CREATE_NOTE:
return [
...state,
{
id: state.length,
content: action.txt,
completed: false
}
]
case TOGGLE_TODO:
return state.map(todo =>
(todo.id === action.id)
? {...todo, completed: !todo.completed }
: todo
)
default:
return state;
}
}
const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';
const vFilters = { SHOW_ALL: 'SHOW_ALL', SHOW_ACTIVE: 'SHOW_ACTIVE', SHOW_COMPLETED: 'SHOW_COMPLETED' }
// Visibility filter reducer
const visibilityReducer = (state = vFilters.SHOW_ALL, action) => {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter
default:
return state
}
}
/***************************
Create todo app
***************************/
const todoApp = combineReducers({
todosReducer,
visibilityReducer
});
const store = createStore(todoApp);
// Subscribe state change
store.subscribe(() => {
const state = store.getState();
console.log(state);
createTodoList( getVisibleTodos(state.todosReducer, state.visibilityReducer) );
});
const createTodoList = (todos) => {
const ul = document.getElementById("todo-list");
// Delete all todos
while (ul.firstChild) ul.removeChild(ul.firstChild);
// Creare todos
todos.forEach(todo => {
// Create elements
let li = document.createElement("li");
let input = document.createElement("input");
let label = document.createElement("label");
li.appendChild(input);
li.appendChild(label);
ul.appendChild(li);
// Set attributes
input.setAttribute("type", "checkbox");
input.setAttribute("id", "todo"+todo.id);
label.setAttribute("for", "todo"+todo.id);
li.className = 'collection-item';
label.innerHTML = todo.content;
if (todo.completed) input.checked = true;
// Dispatch toggle action when clicked
label.onclick = () => {
setTimeout(() => store.dispatch({type: TOGGLE_TODO, id: todo.id}), 1000);
};
});
}
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case vFilters.SHOW_ALL:
return todos
case vFilters.SHOW_COMPLETED:
return todos.filter(t => t.completed)
case vFilters.SHOW_ACTIVE:
return todos.filter(t => !t.completed)
default:
throw new Error('Unknown filter: ' + filter)
}
}
/***************************
Add event lisner
***************************/
document.getElementById("add-btn").onclick = () => {
const txt = document.getElementById("new-todo").value
store.dispatch({type: CREATE_NOTE, txt});
document.getElementById("new-todo").value = "";
};
document.getElementById("show-all-label").onclick = () => {
store.dispatch({type: SET_VISIBILITY_FILTER, filter: vFilters.SHOW_ALL});
};
document.getElementById("show-active-label").onclick = () => {
store.dispatch({type: SET_VISIBILITY_FILTER, filter: vFilters.SHOW_ACTIVE});
};
document.getElementById("show-completed-label").onclick = () => {
store.dispatch({type: SET_VISIBILITY_FILTER, filter: vFilters.SHOW_COMPLETED});
};
/***************************
Initialize todo app
***************************/
store.dispatch({type: CREATE_NOTE, txt: "Smaple text1"});
store.dispatch({type: CREATE_NOTE, txt: "Smaple text2"});
store.dispatch({type: TOGGLE_TODO, id: 0});
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment