-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscript_old.js
269 lines (237 loc) · 8.04 KB
/
script_old.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
"use strict";
/* State and initializing
========================================================================== */
// DOM elements
const taskForm = document.getElementById("task-form");
const input = document.getElementById("input");
const taskList = document.getElementById("task-list");
const clearButton = document.getElementById("clear-btn");
const apiUrl = "http://localhost:4730/todos";
// Modal Styling
const corner = Swal.mixin({
toast: true,
position: "top-end",
title: "Sorry, API is offline!",
text: "Start server with: npm run start",
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
},
});
// State
const state = {
currentFilter: "all", // "all", "done", "open"
tasks: [],
};
initialize();
/* FUNCTION - to render filtered data from state
========================================================================== */
function render() {
taskList.innerHTML = "";
// Filtering todos
const filteredTodos = state.tasks.filter((task) => {
if (state.currentFilter == "done") {
return task.done; // set task to done
}
if (state.currentFilter == "open") {
return !task.done; // set task to NOT done
}
return true; // unfiltered tasks
});
for (const task of filteredTodos) {
taskList.appendChild(generateTodoItemTemplate(task));
}
}
/* FUNCTION - to get todos from the API
========================================================================== */
function getTodosFromApi() {
fetch(apiUrl)
.then((response) => response.json())
.then((todosFromApi) => {
state.tasks = todosFromApi;
render();
})
.catch((error) => {
console.error("Error getting todos from API:", error);
corner.fire({
icon: "error",
title: "Sorry, API is offline!",
});
});
//.finally(() => console.log("test if api is online and offline"));
}
/* FUNCTION - to save a new todo to the API
========================================================================== */
function saveTodoToApi() {
const newTodoText = input.value.trim();
const newTodo = { description: newTodoText, done: false };
fetch(apiUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(newTodo),
})
.then((response) => response.json())
.then((newTodoFromApi) => {
state.tasks.push(newTodoFromApi);
render();
})
.catch((error) => console.error("Error saving todo to API:", error));
}
/* FUNCTION - to update a todo in the API
========================================================================== */
function updateTodoToApi(task) {
fetch(apiUrl + `/${task.id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(task),
})
.then((response) => response.json())
.then((updatedTodoFromApi) => {
// finding the position from the changed task in the local state
const index = state.tasks.findIndex(
(task) => task.id === updatedTodoFromApi.id
);
// -1 means: not in this array
if (index !== -1) {
state.tasks[index] = updatedTodoFromApi;
render();
} else {
console.warn("Updated task not found in local state.");
}
})
.catch((error) => console.error("Error updating todo in API:", error));
}
/* FUNCTION - to delete a todo from the API
========================================================================== */
function deleteTodoFromApi(taskId) {
fetch(apiUrl + `/${taskId}`, {
method: "DELETE",
headers: { "Content-Type": "application/json" },
})
.then(() => {
// Remove the task with the specified id from the state.tasks array
state.tasks = state.tasks.filter((task) => task.id !== parseInt(taskId));
render();
})
.catch((error) => console.error("Error deleting todo from API:", error));
}
/* FUNCTION - to remove all completed todos from the API
========================================================================== */
function removeDoneTodosFromApi() {
// Filter out completed todos from the current state
const doneTodos = state.tasks.filter((task) => task.done);
// Use Promise.all for multiple API requests and delete many completed todos
Promise.all(
doneTodos.map((doneTodo) =>
fetch(apiUrl + `/${doneTodo.id}`, {
method: "DELETE",
headers: { "Content-Type": "application/json" },
})
)
)
.then(() => {
// Update the local state by filtering out completed todos
state.tasks = state.tasks.filter((task) => !task.done);
render();
})
.catch((error) =>
console.error("Error removing done todos from API:", error)
);
}
/* FUNCTION - to generate HTML template for a todo item
========================================================================== */
function generateTodoItemTemplate(task) {
const li = document.createElement("li");
li.classList.add("task-item");
li.id = `task-${task.id}`;
const div = document.createElement("div");
div.classList.add("checkbox-wrapper");
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = `checkbox-toogle-${task.id}`;
checkbox.classList.add("toggle-complete");
checkbox.checked = task.done;
/* EVENT LISTENER - for changing the checkbox status
========================================================================== */
checkbox.addEventListener("change", () => {
task.done = checkbox.checked;
checkbox.checked
? checkbox.setAttribute("checked", "")
: checkbox.removeAttribute("checked");
// Check if the task is already in the API
const existingTask = state.tasks.find((t) => t.id === task.id);
if (existingTask) {
// If present, update the task in the API
updateTodoToApi(task);
} else {
// If not present, it's a new task. Handle this case if needed.
console.warn("Task not found in API.");
}
});
const label = document.createElement("label");
label.innerText = task.description;
label.htmlFor = `checkbox-toggle-${task.id}`;
const button = document.createElement("button");
button.type = "button";
button.textContent = "X";
button.classList.add("delete-task");
button.id = `delete-btn-${task.id}`;
/* EVENT LISTENER - for delete one task
========================================================================== */
button.addEventListener("click", (event) => {
const taskId = parseInt(event.target.id.replace("delete-btn-", ""), 10);
deleteTodoFromApi(taskId);
});
div.append(checkbox, label);
li.append(div, button);
return li;
}
/* EVENT LISTENER - for submit form
========================================================================== */
taskForm.addEventListener("submit", (event) => {
event.preventDefault();
const isDuplicate = state.tasks.some(
(task) =>
task.description.toLowerCase() === input.value.trim().toLowerCase()
);
if (isDuplicate) {
Swal.fire({
position: "center",
popup: "swal2-show",
title: "Sorry",
text: "You can't add a duplicate task!",
icon: "warning",
confirmButtonText: "OK, thanks",
});
} else if (input.value.trim() !== "") {
render();
saveTodoToApi();
input.value = "";
input.focus();
}
});
/* EVENT LISTENER - for filter radio buttons
========================================================================== */
const filterRadios = document.querySelectorAll('input[name="filter"]');
filterRadios.forEach((radio) => {
radio.addEventListener("change", () => {
state.currentFilter = radio.value;
render();
});
});
/* EVENT LISTENER - for clearing completed tasks
========================================================================== */
clearButton.addEventListener("click", () => {
if (confirm("Do you really want to delete all completed tasks?")) {
removeDoneTodosFromApi();
}
});
/* Function to initialize the application
========================================================================== */
function initialize() {
getTodosFromApi();
render();
}