JSFiddle - React, Tailwind, and code Playground
by Cyberpunk3351
HTML
<div id="app">
<h2>Todo:</h2>
<ol class="tasks">
<task-element
v-for="(n, i) in todos"
:key="n.id"
:task="n"
@update="Object.assign(n, $event)"
@delete="todos.splice(i, 1)"
></task-element>
</ol>
<h3>Add new task:</h3>
<input
placeholder="New Todo"
aria-label="Full name"
v-model="newTodo"
@keypress.enter="addTodo"
>
<button type="button" @click="addTodo">Add task</button>
</div>
CSS
body {
background: #20262E;
padding: 20px;
font-family: monospace;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
width: 250px;
border-bottom: 1px solid #ccc;
margin-bottom: 20px;
}
label.islong span::before {
content: "⌛";
}
div.loaded ol.tasks li span {
opacity: 1;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
Vue
Vue.component('task-element',{
props: [ 'task' ],
data : function () {
var d = {seconds_elapsed: null};
return d;
},
methods: {
timer() {
this.seconds_elapsed = (Date.now() - this.task.startTime) / 1000 | 0;
setTimeout(this.timer, 1000);
}
},
created() {
if (!this.task.startTime)
this.$set(this.task, 'startTime', Date.now());
this.timer();
},
template : `
<li>
<label :class="{ islong: task.text.length >= 15 }">
<input type="checkbox" v-model="done">
<span>{{ task.text }}</span>
<small>{{ seconds_elapsed }} seconds ago</small>
</label>
<button v-if="task.done" @click="$emit('delete')">delete</button>
</li>`,
computed: {
done: {
get() {
return this.task.done;
},
set(done) {
this.$emit('update', { done });
},
},
},
});
new Vue({
el: '#app',
data: {
newTodo: '',
todos: [
{ id: 1, text: 'Task 1', done: false },
{ id: 2, text: 'Task 2', done: false },
{ id: 3, text: 'Task 3', done: true },
],
data_is_loaded: true,
},
methods: {
addTodo() {
if(this.newTodo.length > 10) {
const text = this.newTodo;
if (text.length) {
this.todos.push({
id: 1 + Math.max(0, ...this.todos.map(n => n.id)),
text,
done: false,
});
this.newTodo = '';
} else {
alert('empty');
}
}},
},
});