This commit is contained in:
2025-08-28 14:34:18 +02:00
commit 5ff4c53a10
29 changed files with 1705 additions and 0 deletions

24
TP4/EX3/index.html Normal file
View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Todo List avec Router</title>
<script src="https://cdn.jsdelivr.net/npm/riot@6.0.1/riot.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/riot-route@4.0.0/dist/route.min.js"></script>
<style>
body { font-family: sans-serif; display: flex; flex-direction: column; align-items: center; padding: 20px; }
.filters a { margin: 0 5px; padding: 5px 10px; border: 1px solid #ccc; text-decoration: none; color: #333; }
.filters a.active { background-color: #eee; }
.done { text-decoration: line-through; color: #999; }
ul { list-style: none; padding: 0; }
li { margin: 5px 0; display: flex; align-items: center; gap: 10px; }
</style>
</head>
<body>
<todo-router></todo-router>
<script type="module">
import './todo-router.riot';
riot.mount('todo-router');
</script>
</body>
</html>

98
TP4/EX3/todo-router.riot Normal file
View File

@@ -0,0 +1,98 @@
<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>