-
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 #152 from Konkuk-KUIT/hyungyu
[9주차] 미션 완료
- Loading branch information
Showing
6 changed files
with
499 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,135 @@ | ||
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:8080/todos"; | ||
// fetch(API_URL) | ||
// .then((response) => response.json() as Promise<Todo[]>) | ||
// .then((data: Todo[]) => renderTodo(data)); | ||
const fetchTodos = () => __awaiter(this, void 0, void 0, function* () { | ||
const response = yield fetch(API_URL); | ||
return yield response.json(); | ||
}); | ||
const updateTodo = (todoId, originalTitle) => __awaiter(this, void 0, void 0, function* () { | ||
const todoItem = document.querySelector(`#todo-${todoId}`); | ||
if (!todoItem) | ||
return; | ||
const inputEl = document.createElement("input"); | ||
inputEl.type = "text"; | ||
inputEl.value = originalTitle; | ||
const updateButton = document.createElement("button"); | ||
updateButton.textContent = "수정"; | ||
inputEl.focus(); | ||
const updateButtonClicked = () => __awaiter(this, void 0, void 0, function* () { | ||
const updatedTitle = inputEl.value; | ||
yield fetch(`${API_URL}/${todoId}`, { | ||
method: "PUT", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ title: updatedTitle }), | ||
}); | ||
// .then((response) => response.json()) | ||
// .then(() => fetch(API_URL)) | ||
// .then((response) => response.json()) | ||
// .then((data) => renderTodo(data)); | ||
const todos = yield fetchTodos(); | ||
renderTodo(todos); | ||
if (todoInputEl) | ||
todoInputEl.focus(); | ||
}); | ||
inputEl.addEventListener('keydown', (event) => { | ||
if (event.key === 'Enter') { | ||
updateButtonClicked(); | ||
} | ||
}); | ||
updateButton.onclick = updateButtonClicked; | ||
todoItem.innerHTML = ""; | ||
todoItem.append(inputEl); | ||
todoItem.append(updateButton); | ||
}); | ||
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 udpateEl = document.createElement("span"); | ||
udpateEl.textContent = "✏️"; | ||
udpateEl.onclick = () => updateTodo(todo.id, todo.title); | ||
listEl.append(deleteEl); | ||
listEl.append(udpateEl); | ||
todoListEl.append(listEl); | ||
}); | ||
if (todoInputEl) | ||
todoInputEl.focus(); | ||
}; | ||
const addTodo = () => __awaiter(this, void 0, void 0, function* () { | ||
if (!todoInputEl) | ||
return; | ||
const title = todoInputEl.value; | ||
const date = new Date(); | ||
const createdAt = date.toDateString(); | ||
if (!title) | ||
return; | ||
const newTodo = { | ||
id: date.getTime(), | ||
title, | ||
createdAt, | ||
}; | ||
yield fetch(API_URL, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify(Object.assign(Object.assign({}, newTodo), { completed: false })), | ||
}); | ||
// .then((response) => response.json()) | ||
// .then(() => { | ||
// if(todoInputEl){ | ||
// (todoInputEl as HTMLInputElement).value = ""; | ||
// } | ||
// return fetch(API_URL); | ||
// }) | ||
// .then((response) => response.json()) | ||
// .then((data: Todo[]) => renderTodo(data)); | ||
if (todoInputEl) | ||
todoInputEl.value = ""; | ||
const todos = yield fetchTodos(); | ||
renderTodo(todos); | ||
}); | ||
const deleteTodo = (todoId) => __awaiter(this, void 0, void 0, function* () { | ||
fetch(`${API_URL}/${todoId}`, { | ||
method: "DELETE", | ||
}); | ||
// .then(() => fetch(API_URL)) | ||
// .then((response) => response.json()) | ||
// .then((data) => renderTodo(data)); | ||
const todos = yield fetchTodos(); | ||
renderTodo(todos); | ||
}); | ||
if (todoInputEl) { | ||
todoInputEl.addEventListener('keydown', (event) => { | ||
if (event.key === 'Enter') { | ||
addTodo(); | ||
} | ||
if (todoInputEl) | ||
todoInputEl.focus(); | ||
}); | ||
} | ||
(() => __awaiter(this, void 0, void 0, function* () { | ||
const todos = yield fetchTodos(); | ||
renderTodo(todos); | ||
}))(); |
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,151 @@ | ||
const todoListEl = document.getElementById("todoList") as HTMLUListElement | null; | ||
const todoInputEl = document.getElementById("todoInput") as HTMLInputElement | null; | ||
|
||
const API_URL = "http://localhost:8080/todos"; | ||
|
||
interface Todo { | ||
id: number; | ||
title: string; | ||
createdAt: string; | ||
completed: boolean; | ||
} | ||
|
||
// fetch(API_URL) | ||
// .then((response) => response.json() as Promise<Todo[]>) | ||
// .then((data: Todo[]) => renderTodo(data)); | ||
const fetchTodos = async (): Promise<Todo[]> => { | ||
const response = await fetch(API_URL); | ||
return await response.json(); | ||
}; | ||
|
||
const updateTodo = async (todoId: number, originalTitle: string): Promise<void> => { | ||
const todoItem = document.querySelector(`#todo-${todoId}`) as HTMLElement | null; | ||
if(!todoItem) return; | ||
|
||
const inputEl = document.createElement("input"); | ||
inputEl.type = "text"; | ||
inputEl.value = originalTitle; | ||
|
||
const updateButton = document.createElement("button"); | ||
updateButton.textContent = "수정"; | ||
|
||
const updateButtonClicked = async () => { | ||
const updatedTitle = inputEl.value; | ||
|
||
await fetch(`${API_URL}/${todoId}`, { | ||
method: "PUT", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ title: updatedTitle }), | ||
}); | ||
// .then((response) => response.json()) | ||
// .then(() => fetch(API_URL)) | ||
// .then((response) => response.json()) | ||
// .then((data) => renderTodo(data)); | ||
|
||
const todos = await fetchTodos(); | ||
renderTodo(todos); | ||
if(todoInputEl) todoInputEl.focus(); | ||
}; | ||
|
||
inputEl.addEventListener('keydown', (event) => { | ||
if (event.key === 'Enter') { | ||
updateButtonClicked(); | ||
} | ||
}); | ||
|
||
updateButton.onclick = updateButtonClicked; | ||
|
||
todoItem.innerHTML = ""; | ||
todoItem.append(inputEl); | ||
todoItem.append(updateButton); | ||
}; | ||
|
||
const renderTodo = (newTodos: Todo[]): void => { | ||
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 udpateEl = document.createElement("span"); | ||
udpateEl.textContent = "✏️"; | ||
udpateEl.onclick = () => updateTodo(todo.id, todo.title); | ||
|
||
listEl.append(deleteEl); | ||
listEl.append(udpateEl); | ||
todoListEl.append(listEl); | ||
}); | ||
if(todoInputEl) todoInputEl.focus(); | ||
}; | ||
|
||
const addTodo = async (): Promise<void> => { | ||
if(!todoInputEl) return; | ||
const title = (todoInputEl as HTMLInputElement).value; | ||
const date = new Date(); | ||
const createdAt = date.toDateString(); | ||
|
||
if (!title) return; | ||
|
||
const newTodo: Omit<Todo, "completed"> = { | ||
id: date.getTime(), | ||
title, | ||
createdAt, | ||
}; | ||
|
||
await fetch(API_URL, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ ...newTodo, completed: false }), | ||
}); | ||
// .then((response) => response.json()) | ||
// .then(() => { | ||
// if(todoInputEl){ | ||
// (todoInputEl as HTMLInputElement).value = ""; | ||
// } | ||
// return fetch(API_URL); | ||
// }) | ||
// .then((response) => response.json()) | ||
// .then((data: Todo[]) => renderTodo(data)); | ||
|
||
if(todoInputEl) todoInputEl.value = ""; | ||
const todos = await fetchTodos(); | ||
renderTodo(todos); | ||
}; | ||
|
||
const deleteTodo = async (todoId: number): Promise<void> => { | ||
console.log(`Attempting to delete todo with id: ${todoId}`); | ||
await fetch(API_URL + '/' + todoId, { | ||
method: "DELETE", | ||
}); | ||
// .then(() => fetch(API_URL)) | ||
// .then((response) => response.json()) | ||
// .then((data) => renderTodo(data)); | ||
|
||
const todos = await fetchTodos(); | ||
renderTodo(todos); | ||
}; | ||
|
||
if(todoInputEl){ | ||
todoInputEl.addEventListener('keydown', (event: KeyboardEvent) => { | ||
if (event.key === 'Enter') { | ||
addTodo(); | ||
} | ||
if(todoInputEl) todoInputEl.focus(); | ||
}); | ||
} | ||
|
||
(async () => { | ||
const todos = await fetchTodos(); | ||
renderTodo(todos); | ||
})(); |
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,22 @@ | ||
{ | ||
"todos": [ | ||
{ | ||
"id": "1732794159114", | ||
"title": "e", | ||
"createdAt": "Thu Nov 28 2024", | ||
"completed": false | ||
}, | ||
{ | ||
"id": "1732794160247", | ||
"title": "f", | ||
"createdAt": "Thu Nov 28 2024", | ||
"completed": false | ||
}, | ||
{ | ||
"id": 1732857303385, | ||
"title": "why", | ||
"createdAt": "Fri Nov 29 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 id="addButton" onclick="addTodo()">Add</button> | ||
</div> | ||
<ul id="todoList"></ul> | ||
</div> | ||
<script src="app.js"></script> | ||
</body> | ||
</html> |
Oops, something went wrong.