|
<!DOCTYPE html> |
|
<html lang="en"> |
|
|
|
<head> |
|
<meta charset="utf-8"> |
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no"> |
|
<link rel="shortcut icon" href="https://alpinejs.dev/favicon.png"> |
|
|
|
<title>Alpine JS</title> |
|
|
|
<!-- Bulma --> |
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css"> |
|
|
|
<!-- Font-awesome --> |
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> |
|
|
|
<!-- Alpine --> |
|
<script defer src="https://unpkg.com/alpinejs"></script> |
|
<!-- https://github.com/devboyarif/alpinejs-crud/blob/master/index.html --> |
|
<!-- https://github.com/danharrin/alpine-tailwind-components/blob/main/select/index.html --> |
|
|
|
<style> |
|
.is-done { |
|
text-decoration: line-through; |
|
} |
|
</style> |
|
|
|
</head> |
|
|
|
<body class="mt-3"> |
|
<div |
|
class="container" |
|
x-data="getTodos()" |
|
x-init="$watch('task', value => {if (value.length > 0) required=false})" |
|
> |
|
<div> |
|
<form |
|
@submit.prevent="saveData" |
|
class="form-inline" |
|
> |
|
<div class="field is-grouped"> |
|
<div class="field"> |
|
<div class="control"> |
|
<input |
|
class="input" |
|
type="text" |
|
maxlength="20" |
|
class="input" |
|
:class="required ? 'is-danger' : ''" |
|
placeholder="Tarefa" |
|
x-model="task" |
|
autofocus |
|
> |
|
</div> |
|
<p |
|
class="help is-danger" |
|
x-show="required" |
|
> |
|
Favor preencher a tarefa. |
|
</p> |
|
<p |
|
class="help has-text-right" |
|
x-show="task.length" |
|
x-text="task.length" |
|
></p> |
|
</div> |
|
<p class="control"> |
|
<button |
|
class="button is-info ml-3" |
|
type="submit" |
|
> |
|
OK |
|
</button> |
|
</p> |
|
</div> |
|
</form> |
|
<table> |
|
<tbody> |
|
<template |
|
x-for="todo in todos" |
|
:key="todo.id" |
|
> |
|
<tr> |
|
<td |
|
:class="todo.done ? 'is-done' : ''" |
|
x-text="todo.task" |
|
@click="toggleDone(todo.id, todo.done ? false : true)" |
|
></td> |
|
<td> |
|
<i |
|
class="fa fa-times has-text-danger ml-3" |
|
@click="deleteTask(todo.id)" |
|
></i> |
|
</td> |
|
</tr> |
|
</template> |
|
</tbody> |
|
</table> |
|
</div> |
|
</div> |
|
|
|
<script> |
|
const getTodos = () => ({ |
|
url: 'http://localhost:3000/todos', |
|
todos: [], |
|
task: '', |
|
required: false, |
|
init() { |
|
fetch(this.url) |
|
.then(response => response.json()) |
|
.then(data => this.todos = data) |
|
}, |
|
saveData() { |
|
if (!this.task) { |
|
this.required = true |
|
return |
|
} |
|
fetch(this.url, { |
|
method: 'POST', |
|
headers: { 'Content-Type': 'application/json' }, |
|
body: JSON.stringify({ |
|
task: this.task |
|
}) |
|
}) |
|
.then(response => response.json()) |
|
.then(() => { |
|
this.init() |
|
this.task = '' |
|
}) |
|
}, |
|
toggleDone(id, value) { |
|
fetch(`http://localhost:3000/todos/${id}`, { |
|
method: 'PATCH', |
|
headers: { 'Content-Type': 'application/json' }, |
|
body: JSON.stringify({ |
|
done: value |
|
}) |
|
}) |
|
.then(response => response.json()) |
|
.then(() => { |
|
this.init() |
|
}) |
|
}, |
|
deleteTask(id) { |
|
fetch(`http://localhost:3000/todos/${id}`, { |
|
method: 'DELETE', |
|
}) |
|
.then(response => response.json()) |
|
.then(() => { |
|
this.init() |
|
}) |
|
}, |
|
}) |
|
</script> |
|
|
|
</body> |
|
|
|
</html> |