- hello world
+
+
+
+
+
+
+
+
+ The sum is:
+
+
diff --git a/awesome_owl/static/src/todo_list/todo_item/todo_item.js b/awesome_owl/static/src/todo_list/todo_item/todo_item.js
new file mode 100644
index 00000000000..38e8f3589d0
--- /dev/null
+++ b/awesome_owl/static/src/todo_list/todo_item/todo_item.js
@@ -0,0 +1,26 @@
+import { Component } from "@odoo/owl";
+
+export class TodoItem extends Component {
+ static template = "awesome_owl.todo_item";
+
+ static props = {
+ todo: {
+ type: Object,
+ shape: {
+ id: { type: Number },
+ description: { type: String },
+ isCompleted: { type: Boolean },
+ },
+ },
+ toggleState: Function,
+ removeTodo: Function,
+ };
+
+ onChange() {
+ this.props.toggleState(this.props.todo.id);
+ }
+
+ onDelete() {
+ this.props.removeTodo(this.props.todo.id);
+ }
+}
diff --git a/awesome_owl/static/src/todo_list/todo_item/todo_item.xml b/awesome_owl/static/src/todo_list/todo_item/todo_item.xml
new file mode 100644
index 00000000000..55edbde6ee0
--- /dev/null
+++ b/awesome_owl/static/src/todo_list/todo_item/todo_item.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/awesome_owl/static/src/todo_list/todo_list.js b/awesome_owl/static/src/todo_list/todo_list.js
new file mode 100644
index 00000000000..b34fc3a93d9
--- /dev/null
+++ b/awesome_owl/static/src/todo_list/todo_list.js
@@ -0,0 +1,48 @@
+import { Component, useState } from "@odoo/owl";
+import { TodoItem } from "./todo_item/todo_item";
+import { useAutofocus } from "../utils";
+
+export class TodoList extends Component {
+ static template = "awesome_owl.todo_list";
+
+ static components = { TodoItem };
+
+ setup() {
+ this.state = useState({
+ todos: [],
+ });
+ this.addTodo = this.addTodo.bind(this);
+ this.toggleTodo = this.toggleTodo.bind(this);
+ this.removeTodo = this.removeTodo.bind(this);
+ useAutofocus("input");
+ }
+
+ addTodo(ev) {
+ if (ev.keyCode === 13 && ev.target.value.trim() !== "") {
+ const newId =
+ this.state.todos.length > 0
+ ? Math.max(...this.state.todos.map((todo) => todo.id)) + 1
+ : 1;
+ this.state.todos.push({
+ id: newId,
+ description: ev.target.value,
+ isCompleted: false,
+ });
+ ev.target.value = "";
+ }
+ }
+
+ toggleTodo(todoId) {
+ const todo = this.state.todos.find((todo) => todo.id === todoId);
+ if (todo) {
+ todo.isCompleted = !todo.isCompleted;
+ }
+ }
+
+ removeTodo(todoId) {
+ const index = this.state.todos.findIndex((todo) => todo.id === todoId);
+ if (index >= 0) {
+ this.state.todos.splice(index, 1);
+ }
+ }
+}
diff --git a/awesome_owl/static/src/todo_list/todo_list.xml b/awesome_owl/static/src/todo_list/todo_list.xml
new file mode 100644
index 00000000000..5be3fea5d45
--- /dev/null
+++ b/awesome_owl/static/src/todo_list/todo_list.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/awesome_owl/static/src/utils.js b/awesome_owl/static/src/utils.js
new file mode 100644
index 00000000000..27ec0aab507
--- /dev/null
+++ b/awesome_owl/static/src/utils.js
@@ -0,0 +1,9 @@
+import { useRef, onMounted } from "@odoo/owl";
+
+export function useAutofocus(refName) {
+ const ref = useRef(refName);
+ onMounted(() => {
+ ref.el.focus();
+ });
+ return { ref };
+}