-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat] Todo List 구현 #2
Open
yoouyeon
wants to merge
15
commits into
main
Choose a base branch
from
jeyoon
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
d4a0cc2
[Feat] todo 생성기능 구현
yoouyeon 8da5f25
[Feat] todo 삭제기능 구현
yoouyeon 66fb500
[Feat] todo 수정기능 구현
yoouyeon 294a7e8
[Fix] 기존 내용 수정 input에 안들어가던 문제 수정
yoouyeon 59d4c9c
[Style] 기본 css 적용
yoouyeon 0bde221
[Style] 수정기능 css 적용
yoouyeon f16f9da
[Chore] 불필요한 주석 삭제
yoouyeon 9e4705e
[Feat] todo 수정 취소 기능 추가
yoouyeon 38126e0
[Style] 제목과 폰트 추가
yoouyeon 4fa200e
[Feat] todo 완료 기능 추가
yoouyeon f556c94
[Fix] 수정 시 Input 태그 CSS 누락 수정
yoouyeon d9f329c
[Docs] README 기능설명 추가
yoouyeon e253cde
[Docs] README 이미지 배치 수정
yoouyeon aa8e6c7
[Docs] 배포 링크 추가
yoouyeon 8d87dc8
Update README.md
yoouyeon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 |
---|---|---|
@@ -1,25 +1,23 @@ | ||
# 42gg 프론트엔드 온보딩 1단계 | ||
# 42gg 프론트엔드 온보딩 1단계 | ||
|
||
## 공통 조건 | ||
## 📝 ToDo List 만들기 | ||
|
||
- 온보딩 프로젝트는 개인 계정으로 fork하여 진행하고 PR로 제출합니다. | ||
- git / github / code 컨벤션은 42gg notion에 있는 자료를 적극 반영합니다. | ||
- 기본 기능 외 추가 기능, 디자인 구현은 자유입니다. | ||
- 최종 제출품에는 README 작성이 되있어야 합니다.([예시](https://github.com/42organization/42gg.client/blob/main/README.md)) | ||
[✨ 배포 페이지 ✨](https://verysimpletodolist.netlify.app/) | ||
|
||
## todo list 만들기 | ||
## ✨ 주요 기능 소개 | ||
|
||
- (필수) Javascript, HTML, CSS | ||
- (필수) todo 생성(Create), 조회(Read) 기능 구현하기 (새로고침 고려 X) | ||
- (선택) todo 수정(Update), 삭제(Delete) 기능 구현하기 (새로고침 고려 X) | ||
- (선택) 디자인 적용하기 | ||
- (선택) 무료로 배포하기 | ||
### ✏️ 할 일을 추가할 수 있습니다 | ||
|
||
## 참고 | ||
<img width="40%" alt="add_todo_1" src="https://user-images.githubusercontent.com/57761286/228439216-82f423e9-c84a-4361-8e28-608522ca0e92.png"> <img width="40%" alt="add_todo_2" src="https://user-images.githubusercontent.com/57761286/228439232-5b2b5ed7-3e09-4368-af9d-e469ac3481e0.png"> | ||
|
||
- 데이터 관리는 하단의 방식 중 하나 선택하시면 됩니다. | ||
- localstorage | ||
- local server(예. [https://github.com/shal0mdave/todo-api.git](https://github.com/shal0mdave/todo-api.git), lowdb) | ||
- mock api(예. [https://dummyjson.com/](https://dummyjson.com/)) | ||
- todo list를 구현하기 위해 필요한 기능들을 미리 생각(그려보고)해보고, 구현해보세요. | ||
- 궁금한 사항은 issue에 등록해주세요. | ||
### ✏️ 할 일을 삭제할 수 있습니다 | ||
|
||
<img width="40%" alt="SimpleTodo_ScreenShoot_7" src="https://user-images.githubusercontent.com/57761286/228441771-4c83b9ae-6625-4ff3-9693-bca3a2aed86c.png"> <img width="40%" alt="SimpleTodo_ScreenShoot_8" src="https://user-images.githubusercontent.com/57761286/228441788-087d1429-a4d8-4d46-8109-b2aefbd483a2.png"> | ||
|
||
### ✏️ 할 일을 수정할 수 있습니다 | ||
|
||
<img width="40%" alt="update_todo_1" src="https://user-images.githubusercontent.com/57761286/228439558-fb3ac233-dadf-47fc-9a4f-a7a9e96e999d.png"> <img width="40%" alt="update_todo_2" src="https://user-images.githubusercontent.com/57761286/228439549-f6ec3208-9439-4197-8cc8-711c94ec81ef.png"> | ||
|
||
### ✏️ 완료한 할 일은 클릭하여 완료표시할 수 있습니다 | ||
|
||
<img width="40%" alt="complete_todo_1" src="https://user-images.githubusercontent.com/57761286/228440361-16b07f81-9e02-4314-8719-ee2dda325fe2.png"> <img width="40%" alt="complete_todo_2" src="https://user-images.githubusercontent.com/57761286/228440357-0ae16e3c-5334-4db0-8c4e-c9a913d55f54.png"> |
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,26 @@ | ||
<!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"> | ||
<link rel="preconnect" href="https://fonts.googleapis.com"> | ||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | ||
<link href="https://fonts.googleapis.com/css2?family=Lilita+One&family=Nanum+Gothic&display=swap" rel="stylesheet"> | ||
<link rel="stylesheet" href="./styles.css"> | ||
<title>Simple ToDo</title> | ||
</head> | ||
<body> | ||
<h1>SIMPLE TODO LIST</h1> | ||
<div id="todo-wrapper"> | ||
<form id="todo-form"> | ||
<input id="todo-input" autocomplete="off" placeholder="TODO 추가하기" type="text" required> | ||
</form> | ||
<hr /> | ||
<ul id="todo-list"> | ||
<!-- Dynamically added --> | ||
</ul> | ||
</div> | ||
Comment on lines
+15
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 의도하신건지 모르겠다만 고정적인 부분은 미리 선언하셔서 좋은거 같아요 👍 |
||
<script src="./todo.js"></script> | ||
</body> | ||
</html> |
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,123 @@ | ||
* { | ||
font-family: 'Nanum Gothic', sans-serif; | ||
} | ||
|
||
html { | ||
height: 100vh; | ||
} | ||
body { | ||
display: flex; | ||
flex-direction: column; | ||
height: 100%; | ||
margin: 0; | ||
background: linear-gradient(45deg, #6190E8, #A7BFE8); | ||
justify-content: center; | ||
align-items: center; | ||
} | ||
|
||
h1 { | ||
font-family: 'Lilita One', sans-serif, cursive; | ||
font-size: 3rem; | ||
color: #F5F9FC; | ||
margin: 0 0 10px 0; | ||
} | ||
|
||
#todo-wrapper { | ||
display: flex; | ||
flex-direction: column; | ||
width: 500px; | ||
height: 400px; | ||
padding: 30px; | ||
background: #F5F9FC; | ||
border-radius: 10px; | ||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); | ||
color: #333333; | ||
} | ||
|
||
@media (max-height: 500px) { | ||
#todo-wrapper { | ||
height: 300px; | ||
} | ||
} | ||
Comment on lines
+37
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 미디어쿼리를 사용하셨는데 해당 스타일이 어떤 목적으로 사용되는지 알려주세요 |
||
|
||
#todo-wrapper hr { | ||
width: 100%; | ||
height: 2px; | ||
margin: 20px 0; | ||
border: 0; | ||
background-color: #FFD24C; | ||
} | ||
|
||
#todo-form { | ||
width: 100%; | ||
} | ||
|
||
#todo-form input { | ||
height: 2rem; | ||
width: 100%; | ||
padding: 0 7px; | ||
box-sizing: border-box; | ||
border: 1.5px solid #92B4EC; | ||
border-radius: 10px; | ||
outline: none; | ||
} | ||
|
||
#todo-list { | ||
flex: 1; | ||
width: 100%; | ||
height: 100%; | ||
padding: 0; | ||
margin: 0; | ||
list-style: none; | ||
overflow: auto; | ||
} | ||
|
||
#todo-list li { | ||
display: flex; | ||
height: fit-content; | ||
padding: 10px; | ||
margin-bottom: 10px; | ||
border: 1.5px solid #6190E8; | ||
border-radius: 10px; | ||
background-color: #FFFFFF; | ||
} | ||
|
||
#todo-list li > div { | ||
flex: 1; | ||
padding: 0 10px; | ||
text-align: left; | ||
word-break: break-all; | ||
word-wrap: break-word; | ||
} | ||
|
||
#todo-list li.completed { | ||
border: 1.5px solid #FFD24C; | ||
background-color: #F5F9FC; | ||
} | ||
|
||
#todo-list li.completed > div { | ||
text-decoration: line-through; | ||
color: #92B4EC; | ||
} | ||
|
||
#todo-list li form > input { | ||
height: 2rem; | ||
width: 100%; | ||
padding: 0 7px; | ||
box-sizing: border-box; | ||
border: 1.5px solid #92B4EC; | ||
border-radius: 10px; | ||
outline: none; | ||
} | ||
|
||
#todo-list li > button { | ||
border: none; | ||
background: none; | ||
color: #92B4EC; | ||
text-align: right; | ||
} | ||
|
||
#todo-list li > button:hover { | ||
color: #6190E8; | ||
cursor: pointer | ||
} |
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 @@ | ||
const todoForm = document.getElementById('todo-form'); | ||
const todoInput = document.getElementById('todo-input'); | ||
const todoList = document.getElementById('todo-list'); | ||
|
||
// Initialize | ||
|
||
const TODO_KEY = 'todoData' | ||
let todoData = JSON.parse(localStorage.getItem(TODO_KEY)) || []; | ||
todoData.map(printTodo); | ||
|
||
todoForm.addEventListener('submit', handleTodoSubmit); | ||
|
||
// Event Handlers | ||
|
||
function handleTodoSubmit(event) { | ||
event.preventDefault(); // 새로고침 방지 | ||
const newTodo = { | ||
id: Date.now(), // 현재 시간의 밀리초를 id로 사용 | ||
text: todoInput.value, | ||
completed: false, | ||
} | ||
todoInput.value = ''; | ||
printTodo(newTodo); | ||
addTodo(newTodo); | ||
} | ||
|
||
function handleTodoDelete(event) { | ||
const targetId = parseInt(event.target.parentElement.id); | ||
const li = event.target.parentElement; // 삭제할 li | ||
li.remove(); | ||
todoData = todoData.filter((todo) => { return (todo.id !== targetId); }); | ||
saveTodo(); | ||
} | ||
|
||
function handleTodoUpdate(event) { | ||
const li = event.target.parentElement; // 수정할 Todo | ||
const div = li.querySelector('div'); | ||
const updateButton = li.querySelector('.update'); | ||
updateButton.innerText = '취소'; | ||
updateButton.removeEventListener('click', handleTodoUpdate); | ||
updateButton.addEventListener('click', handleTodoUpdateCancel); | ||
const form = document.createElement('form'); | ||
form.addEventListener('submit', handleChangedTodoSubmit); | ||
const updateInput = document.createElement('input'); | ||
updateInput.type = 'text'; | ||
updateInput.value = div.innerText; | ||
div.innerText = ''; | ||
div.appendChild(form); | ||
form.appendChild(updateInput); | ||
} | ||
|
||
function handleChangedTodoSubmit(event) { | ||
event.preventDefault(); | ||
const form = event.target; | ||
const todoId = parseInt(form.parentElement.parentElement.id); // 수정할 Todo의 id | ||
const div = form.parentElement; // Form 부모 div | ||
const updateInput = form.querySelector('input').value; // 수정할 내용 | ||
const updateButton = div.parentElement.querySelector('.update'); | ||
updateButton.innerText = '수정'; | ||
updateButton.removeEventListener('click', handleTodoUpdateCancel); | ||
updateButton.addEventListener('click', handleTodoUpdate); | ||
div.innerText = updateInput; | ||
form.remove(); | ||
todoData = todoData.map((todo) => { | ||
if (todo.id === todoId) { | ||
todo.text = updateInput; | ||
} | ||
return todo; | ||
}); // 수정한 내용 반영 | ||
saveTodo(); | ||
} | ||
|
||
function handleTodoUpdateCancel(event) { | ||
const li = event.target.parentElement; // 수정할 Todo | ||
const id = parseInt(li.id); | ||
const div = li.querySelector('div'); | ||
const form = div.querySelector('form'); | ||
form.remove(); | ||
const updateButton = li.querySelector('.update'); | ||
updateButton.innerText = '수정'; | ||
updateButton.removeEventListener('click', handleTodoUpdateCancel); | ||
updateButton.addEventListener('click', handleTodoUpdate); | ||
const oldTodo = todoData.find((todo) => todo.id === id); | ||
div.innerText = oldTodo.text; | ||
} | ||
|
||
function handleTodoClick(event) { | ||
const li = event.target.parentElement; | ||
const id = parseInt(li.id); | ||
let completed = true; | ||
todoData.map((todo) => { | ||
if (todo.id === id) { | ||
todo.completed = todo.completed === true ? false : true; | ||
completed = todo.completed; | ||
} | ||
return todo; | ||
}); | ||
li.className = completed ? 'completed' : 'not-completed'; | ||
saveTodo(); | ||
} | ||
|
||
// Functions | ||
|
||
function printTodo (newTodo) { | ||
const li = document.createElement('li'); | ||
li.id = newTodo.id; | ||
li.className = newTodo.completed === true ? 'completed' : 'not-completed'; | ||
const div = document.createElement('div'); | ||
div.addEventListener('click', handleTodoClick); | ||
const updateButton = document.createElement('button'); | ||
updateButton.addEventListener('click', handleTodoUpdate); | ||
updateButton.className = 'update'; | ||
updateButton.innerText = '수정'; | ||
const deleteButton = document.createElement('button'); | ||
deleteButton.addEventListener('click', handleTodoDelete); | ||
deleteButton.className = 'delete'; | ||
deleteButton.innerText = '삭제'; | ||
div.innerText = newTodo.text; | ||
|
||
li.appendChild(div); | ||
li.appendChild(updateButton); | ||
li.appendChild(deleteButton); | ||
todoList.appendChild(li); | ||
} | ||
|
||
function addTodo (newTodo) { | ||
todoData.push(newTodo); | ||
saveTodo(); | ||
} | ||
|
||
function saveTodo () { | ||
localStorage.setItem(TODO_KEY, JSON.stringify(todoData)); | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
폰트 관련해서 link해주셨는데 궁금한게 있어서 질문드립니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.