-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #150 from Konkuk-KUIT/hamxxn
[9주차]
- Loading branch information
Showing
6 changed files
with
487 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
const todoListEl = document.getElementById("todoList"); | ||
const todoInputEl = document.getElementById("todoInput"); | ||
const API_URL = "http://localhost:3000/todos"; | ||
fetch(API_URL) | ||
.then((response) => response.json()) | ||
.then((data) => renderTodo(data)) | ||
.catch((error) => console.log("error: " + error)); | ||
const fetchTodos = () => __awaiter(this, void 0, void 0, function* () { | ||
const response = yield fetch(API_URL); | ||
return yield response.json(); | ||
}); | ||
//post 요청 | ||
const fetchPost = (newToDo) => __awaiter(this, void 0, void 0, function* () { | ||
return yield fetch(API_URL, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify(Object.assign({}, newToDo)), | ||
}).then((response) => response.json()); | ||
}); | ||
const fetchDelete = (todoId) => { | ||
return fetch(API_URL + "/" + todoId, { | ||
method: "DELETE", | ||
}); | ||
}; | ||
//patㅊh | ||
const fetchPatch = (todoId, newTitle) => { | ||
return fetch(API_URL + "/" + todoId, { | ||
method: "PATCH", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
title: newTitle, | ||
}), | ||
}); | ||
}; | ||
//만약 null일 시 return 하도록 return | ||
const renderTodo = (newTodos) => { | ||
if (!todoListEl) | ||
return; | ||
todoListEl.innerHTML = ""; | ||
newTodos.forEach((todo) => { | ||
const listEl = document.createElement("li"); | ||
listEl.textContent = todo.title; | ||
listEl.id = `todo-${todo.id}`; | ||
const deleteEl = document.createElement("span"); | ||
deleteEl.textContent = "🗑️"; | ||
deleteEl.onclick = () => deleteTodo(todo.id); | ||
const updateEl = document.createElement("span"); | ||
updateEl.textContent = "✏️"; | ||
updateEl.onclick = () => updateTodo(todo.id, todo.title); | ||
listEl.append(deleteEl); | ||
listEl.append(updateEl); | ||
todoListEl.append(listEl); | ||
}); | ||
}; | ||
//null 처리 필요 | ||
const addTodo = () => { | ||
if (todoInputEl == null) | ||
return; | ||
const title = todoInputEl.value; | ||
const date = new Date(); | ||
const createdAt = date.toDateString(); | ||
if (!title) | ||
return; | ||
//Omit <Todo,"completed"> => 그냥 개념만 알고 가기 ㅇㅇ | ||
const newTodo = { | ||
id: date.getTime(), | ||
title, | ||
createdAt, | ||
completed: false, | ||
}; | ||
fetchPost(newTodo) | ||
.then(() => { | ||
todoInputEl.value = ""; | ||
return fetchTodos(); | ||
}) | ||
.then((data) => renderTodo(data)); | ||
}; | ||
const deleteTodo = (todoId) => { | ||
if (todoId == null) | ||
return; | ||
fetchDelete(todoId) | ||
.then(() => fetchTodos()) | ||
.then((data) => renderTodo(data)); | ||
}; | ||
const updateTodo = (todoId, title) => { | ||
//id에 해당하는 아이템 불러옴 | ||
const todoItem = document.querySelector(`#todo-${todoId}`); | ||
if (!todoItem) | ||
return; | ||
todoItem.innerHTML = ""; | ||
const updateInput = document.createElement("input"); | ||
updateInput.type = "text"; | ||
updateInput.value = title; | ||
todoItem.append(updateInput); | ||
const updateTodoItem = (event) => { | ||
if (event.key === "Enter") { | ||
const newTitle = updateInput.value.trim(); | ||
if (!newTitle) { | ||
alert("Todo의 title을 입력해주세요."); | ||
return; | ||
} | ||
updateToDoTitle(todoId, updateInput.value) | ||
.then(() => { | ||
todoItem.innerHTML = ""; | ||
return fetchTodos(); | ||
}) | ||
.then((data) => renderTodo(data)) | ||
.catch((error) => { | ||
console.log("error: ", error); | ||
}); | ||
} | ||
}; | ||
updateInput.addEventListener("keydown", updateTodoItem); | ||
}; | ||
//DB 수정 | ||
const updateToDoTitle = (todoId, newTitle) => { | ||
if (!newTitle) | ||
return Promise.reject(new Error("title cannot be empty")); | ||
return fetchPatch(todoId, newTitle); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
const todoListEl = document.getElementById("todoList") as HTMLInputElement; | ||
const todoInputEl = document.getElementById("todoInput") as HTMLInputElement; | ||
|
||
const API_URL = "http://localhost:3000/todos"; | ||
|
||
//Todo 인터페이스 만들기0 | ||
interface ToDo { | ||
id: number; | ||
title: string; | ||
createdAt: string; | ||
completed: boolean; | ||
} | ||
|
||
fetch(API_URL) | ||
.then((response) => response.json()) | ||
.then((data) => renderTodo(data)) | ||
.catch((error) => console.log("error: " + error)); | ||
|
||
const fetchTodos = async (): Promise<ToDo[]> => { | ||
const response = await fetch(API_URL); | ||
return await response.json(); | ||
}; | ||
|
||
//post 요청 | ||
const fetchPost = async (newToDo: ToDo): Promise<ToDo[]> => { | ||
return await fetch(API_URL, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ ...newToDo }), | ||
}).then((response) => response.json()); | ||
}; | ||
const fetchDelete = (todoId: number): Promise<Response> => { | ||
return fetch(API_URL + "/" + todoId, { | ||
method: "DELETE", | ||
}); | ||
}; | ||
|
||
//patㅊh | ||
const fetchPatch = (todoId: number, newTitle: string): Promise<Response> => { | ||
return fetch(API_URL + "/" + todoId, { | ||
method: "PATCH", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
title: newTitle, | ||
}), | ||
}); | ||
}; | ||
|
||
//만약 null일 시 return 하도록 return | ||
const renderTodo = (newTodos: ToDo[]): void => { | ||
if (!todoListEl) return; | ||
todoListEl.innerHTML = ""; | ||
newTodos.forEach((todo: ToDo) => { | ||
const listEl = document.createElement("li"); | ||
listEl.textContent = todo.title; | ||
listEl.id = `todo-${todo.id}`; | ||
|
||
const deleteEl = document.createElement("span"); | ||
deleteEl.textContent = "🗑️"; | ||
deleteEl.onclick = () => deleteTodo(todo.id); | ||
|
||
const updateEl = document.createElement("span"); | ||
updateEl.textContent = "✏️"; | ||
updateEl.onclick = () => updateTodo(todo.id, todo.title); | ||
|
||
listEl.append(deleteEl); | ||
listEl.append(updateEl); | ||
todoListEl.append(listEl); | ||
}); | ||
}; | ||
|
||
//null 처리 필요 | ||
const addTodo = (): void => { | ||
if (todoInputEl == null) return; | ||
const title = todoInputEl.value; | ||
const date = new Date(); | ||
const createdAt = date.toDateString(); | ||
|
||
if (!title) return; | ||
//Omit <Todo,"completed"> => 그냥 개념만 알고 가기 ㅇㅇ | ||
const newTodo: ToDo = { | ||
id: date.getTime(), | ||
title, | ||
createdAt, | ||
completed: false, | ||
}; | ||
fetchPost(newTodo) | ||
.then(() => { | ||
todoInputEl.value = ""; | ||
return fetchTodos(); | ||
}) | ||
.then((data) => renderTodo(data)); | ||
}; | ||
|
||
const deleteTodo = (todoId: number): void => { | ||
if (todoId == null) return; | ||
|
||
fetchDelete(todoId) | ||
.then(() => fetchTodos()) | ||
.then((data) => renderTodo(data)); | ||
}; | ||
|
||
const updateTodo = (todoId: number, title: string): void => { | ||
//id에 해당하는 아이템 불러옴 | ||
const todoItem = document.querySelector(`#todo-${todoId}`) as HTMLElement; | ||
if (!todoItem) return; | ||
todoItem.innerHTML = ""; | ||
|
||
const updateInput = document.createElement("input"); | ||
updateInput.type = "text"; | ||
updateInput.value = title; | ||
todoItem.append(updateInput); | ||
|
||
const updateTodoItem = (event: { key: string }) => { | ||
if (event.key === "Enter") { | ||
const newTitle = updateInput.value.trim(); | ||
if (!newTitle) { | ||
alert("Todo의 title을 입력해주세요."); | ||
return; | ||
} | ||
updateToDoTitle(todoId, updateInput.value) | ||
.then(() => { | ||
todoItem.innerHTML = ""; | ||
return fetchTodos(); | ||
}) | ||
.then((data) => renderTodo(data)) | ||
.catch((error) => { | ||
console.log("error: ", error); | ||
}); | ||
} | ||
}; | ||
|
||
updateInput.addEventListener("keydown", updateTodoItem); | ||
}; | ||
|
||
//DB 수정 | ||
const updateToDoTitle = ( | ||
todoId: number, | ||
newTitle: string | ||
): Promise<Response> => { | ||
if (!newTitle) return Promise.reject(new Error("title cannot be empty")); | ||
return fetchPatch(todoId, newTitle); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"todos": [ | ||
{ | ||
"id": "bfbe", | ||
"title": "하", | ||
"createdAt": "Tue Nov 26 2024", | ||
"completed": false | ||
}, | ||
{ | ||
"id": 1732586913655, | ||
"title": "ㅅㅂ", | ||
"createdAt": "Tue Nov 26 2024", | ||
"completed": false | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
* { | ||
box-sizing: border-box; | ||
margin: 0; | ||
padding: 0; | ||
} | ||
body { | ||
background-color: #f5f5f5; | ||
font-family: "Arial", sans-serif; | ||
} | ||
.app { | ||
width: 400px; | ||
margin: 30px auto; | ||
background-color: #fff; | ||
padding: 20px; | ||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); | ||
} | ||
.header { | ||
font-size: 1.5em; | ||
margin-bottom: 20px; | ||
text-align: center; | ||
} | ||
.inputContainer { | ||
display: flex; | ||
} | ||
#todoInput { | ||
flex: 1; | ||
padding: 10px; | ||
font-size: 1em; | ||
border: 1px solid #ddd; | ||
} | ||
button { | ||
background-color: #28a745; | ||
color: #fff; | ||
padding: 10px; | ||
font-size: 1em; | ||
cursor: pointer; | ||
} | ||
button:hover { | ||
background-color: #218838; | ||
} | ||
ul { | ||
list-style-type: none; | ||
} | ||
li { | ||
padding: 10px; | ||
border-bottom: 1px solid #ddd; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
} | ||
li:last-child { | ||
border-bottom: none; | ||
} | ||
.deleteBtn { | ||
cursor: pointer; | ||
color: #ff0000; | ||
} | ||
.deleteBtn:hover { | ||
text-decoration: underline; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<title>Todo App</title> | ||
<link rel="stylesheet" href="index.css" /> | ||
</head> | ||
<body> | ||
<div class="app"> | ||
<div class="header">My Todos</div> | ||
<div class="inputContainer"> | ||
<input id="todoInput" placeholder="What needs to be done?" /> | ||
<button onclick="addTodo()">Add</button> | ||
</div> | ||
<ul id="todoList"></ul> | ||
</div> | ||
<script src="app.js"></script> | ||
</body> | ||
</html> |
Oops, something went wrong.