98 lines
3.7 KiB
Plaintext
98 lines
3.7 KiB
Plaintext
|
<todo-router>
|
||
|
<h1>Ma Todo List</h1>
|
||
|
<form onsubmit="{ addTodo }">
|
||
|
<input type="text" placeholder="Ajouter une tâche..." value="{ state.newTodoText }">
|
||
|
<button type="submit">Ajouter</button>
|
||
|
</form>
|
||
|
|
||
|
<div class="filters">
|
||
|
<a href="#/all" class="{ active: state.filter === 'all' }">Toutes ({ state.todos.length })</a>
|
||
|
<a href="#/active" class="{ active: state.filter === 'active' }">Actives ({ state.activeTodosCount })</a>
|
||
|
<a href="#/done" class="{ active: state.filter === 'done' }">Terminées ({ state.doneTodosCount })</a>
|
||
|
<button onclick="{ clearDone }" disabled="{ state.doneTodosCount === 0 }">
|
||
|
Effacer les terminées
|
||
|
</button>
|
||
|
</div>
|
||
|
|
||
|
<ul>
|
||
|
<li each="{ todo in state.filteredTodos }" class="{ done: todo.done }">
|
||
|
<input type="checkbox" checked="{ todo.done }" onchange="{ () => toggleTodo(todo.id) }">
|
||
|
<span ondblclick="{ () => editTodo(todo.id) }">{ todo.text }</span>
|
||
|
<button onclick="{ () => deleteTodo(todo.id) }">X</button>
|
||
|
</li>
|
||
|
</ul>
|
||
|
|
||
|
<style>
|
||
|
.done { text-decoration: line-through; color: #999; }
|
||
|
button[disabled] { cursor: not-allowed; opacity: 0.5; }
|
||
|
</style>
|
||
|
|
||
|
<script>
|
||
|
import * as route from 'riot-route';
|
||
|
|
||
|
export default {
|
||
|
onMounted() {
|
||
|
this.loadTodos();
|
||
|
route.start(true);
|
||
|
route.on('route', (collection, id, action) => {
|
||
|
this.update({ filter: collection || 'all' });
|
||
|
this.updateCounts();
|
||
|
});
|
||
|
},
|
||
|
|
||
|
loadTodos() {
|
||
|
const savedTodos = localStorage.getItem('todos');
|
||
|
this.update({ todos: savedTodos ? JSON.parse(savedTodos) : [], filter: route.current[0] || 'all' });
|
||
|
this.updateCounts();
|
||
|
},
|
||
|
|
||
|
saveTodos() {
|
||
|
localStorage.setItem('todos', JSON.stringify(this.state.todos));
|
||
|
this.updateCounts();
|
||
|
},
|
||
|
|
||
|
updateCounts() {
|
||
|
const activeTodosCount = this.state.todos.filter(t => !t.done).length;
|
||
|
const doneTodosCount = this.state.todos.filter(t => t.done).length;
|
||
|
this.update({ activeTodosCount, doneTodosCount, filteredTodos: this.getFilteredTodos() });
|
||
|
},
|
||
|
|
||
|
getFilteredTodos() {
|
||
|
if (this.state.filter === 'active') {
|
||
|
return this.state.todos.filter(todo => !todo.done);
|
||
|
} else if (this.state.filter === 'done') {
|
||
|
return this.state.todos.filter(todo => todo.done);
|
||
|
}
|
||
|
return this.state.todos;
|
||
|
},
|
||
|
|
||
|
addTodo(e) {
|
||
|
e.preventDefault();
|
||
|
const text = this.state.newTodoText.trim();
|
||
|
if (text) {
|
||
|
const newTodo = { id: Date.now(), text, done: false };
|
||
|
this.update({ todos: [...this.state.todos, newTodo], newTodoText: '' });
|
||
|
this.saveTodos();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
deleteTodo(id) {
|
||
|
this.update({ todos: this.state.todos.filter(t => t.id !== id) });
|
||
|
this.saveTodos();
|
||
|
},
|
||
|
|
||
|
toggleTodo(id) {
|
||
|
const updatedTodos = this.state.todos.map(t =>
|
||
|
t.id === id ? { ...t, done: !t.done } : t
|
||
|
);
|
||
|
this.update({ todos: updatedTodos });
|
||
|
this.saveTodos();
|
||
|
},
|
||
|
|
||
|
clearDone() {
|
||
|
this.update({ todos: this.state.todos.filter(t => !t.done) });
|
||
|
this.saveTodos();
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
</todo-router>
|