Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/todo-frontend.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion static/src/component/atom/Button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,4 @@ function Button(props) {
</button>
);
}

export default Button;
2 changes: 1 addition & 1 deletion static/src/component/board/card/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function Card(props) {
<div className='title'>{subject}</div>
{
tasks.map(task => {
return <Task key={task.id} title={task.title} subject={subject} id={task.id} move={move}/>
return <Task remove={props.remove} key={task.id} title={task.title} subject={subject} id={task.id} move={move} created={task.created} assignee={task.assignee} priority={task.priority}/>
})
}

Expand Down
24 changes: 19 additions & 5 deletions static/src/component/board/task/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,36 @@ import {isDone, isTodo, toToggledValue} from "../../../utility/status";
import Button from "../../atom/Button";

function Task(props) {
const {title, subject, id, move} = props;
const {title, subject, id, move, created, assignee, priority} = props;
const onClick = (event) => {
event.stopPropagation();
const toggledValue = toToggledValue(subject);
move(id, toggledValue);
move(id, toggledValue); //board에서 정의해놓은 함수가 실행된다.
};

function handle(event) {
// x 클릭하면 task 삭제 하기
const remove = props.remove; //props로 전달받은 remove를 받는다.
remove(id);
}

return (
<div className='task'>
title : {title}<br/>
{priority}순위<br/>
assignee : {assignee}<br/>
date : {created}
{
isTodo(subject) && <Button className='task-left-btn' onClick={onClick} value='>'/>
isDone(subject)
&& <Button className='task-right-btn' onClick={onClick} value='<'/>
}
{title}
{<Button className='task-remove-btn' onClick={handle} value='X'/>}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{}로 감싸지 않아도 될 거 같아

{
isDone(subject) && <Button className='task-right-btn' onClick={onClick} value='<'/>
isTodo(subject)
&& <Button className='task-left-btn' onClick={onClick} value='>'/>

}

</div>
);
}
Expand Down
4 changes: 4 additions & 0 deletions static/src/css/Enrollment.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,8 @@ label {
display: inline-block;
}

select {
padding: 12px 12px 12px 0;
width:950px;
}

7 changes: 7 additions & 0 deletions static/src/css/Input.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@
border: 1px solid #ccc;
border-radius: 4px;
}

.select{
width: 50%;
padding: 1rem;
border: 1px solid #ccc;
border-radius: 4px;
}
4 changes: 4 additions & 0 deletions static/src/css/Task.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
margin-bottom: 1rem;
padding: 1.5rem;
}
.task-remove-btn{
float:right;
margin : 0px 10px
}

.task-left-btn {
float: right;
Expand Down
76 changes: 62 additions & 14 deletions static/src/page/Board.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, {useEffect, useState} from 'react';
import Card from '../component/board/card';
import getCards from "../service/getCards";
import getCards from '../service/getCards';
import '../css/Board.css';
import moveTo from "../service/moveTo";
import {Link} from "react-router-dom";
import moveTo from '../service/moveTo';
import {Link} from 'react-router-dom';
import {toName, toToggleName} from '../utility/status';
import removeCard from "../service/removeCard";

function Board() {
const [cards, updateCards] = useState({});
useEffect(() => {
useEffect(() => { // 실행했을 때 딱 한번만 실행
(async () => {
const cards = await getCards();
updateCards(cards);
Expand All @@ -17,32 +18,79 @@ function Board() {

const move = async (id, targetStatus) => {
const result = await moveTo(id, targetStatus);
if (!!result) {
if (result) {
const originStatus = toToggleName(targetStatus);
const index = cards[originStatus].findIndex(task => task.id === id);
const index = cards[originStatus].findIndex((task) => task.id === id);
cards[originStatus].splice(index, 1);

const changedStatus = toName(result.status);
cards[changedStatus].push(result);

updateCards({
todo: cards.todo,
done: cards.done
todo: cards.todo.sort(function(a,b){
return a.priority<b.priority?-1:a.priority>b.priority?1:0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아래 33~35번 라인에

function(a,b){
   return a.priority<b.priority?-1:a.priority>b.priority?1:0;
 }

함수하고 중복됬는데, 별도의 함수로 분리하는게 좋을 거 같아~
예를 들어 추후에 다른 정렬 방식을 모두 변경해야 하는 경우,
함수로 정의해뒀다면 해당 함수안에서만 변경해주면 되기 때문에 빠르게 변경사항을 적용할 수 있어

function compare(a,b){
   return a.priority<b.priority?-1:a.priority>b.priority?1:0;
 }

 ...

updateCards({ 
  todo: cards.todo.sort(compare),
  done: cards.done.sort(compare)
});

}),
done: cards.done.sort(function(a,b){
return a.priority<b.priority?-1:a.priority>b.priority?1:0;
}),
});
}
};

function remove(id) {
const isSuccesses = removeCard(id);
if (isSuccesses) {
console.log(id);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

불필요한 콘솔로그는 제거하는 게 좋아~

const todo = cards.todo;
const done = cards.done;
console.log(todo);
console.log(done);

let index = todo.findIndex((value) => { //index 알아내기
return value.id === id;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 코드가 56번 라인의 index = done.findIndex((value) => { return value.id === id;}); 코드하고 비슷한 형식으로 중복되는 것을 볼 수 있는데,

index = done.findIndex((value) => { //index 알아내기
return value.id === id;
});

remove() 함수 인자로 status 값까지 받아온다면, 아래처럼 좀더 일반화된 방식으로 중복 코드를 제거할 수 있을 거 같아~

function remove(id, status) {
       ...
       const index = cards[originStatus].findIndex((task) => task.id === id);
       ...
}

})

if (index !== -1) { //todod에서 찾았을 경우
todo.splice(index,1); //(삭제 시작할 index, 삭제할 개수)
}else{ //todo에서 못찾았을 경우 done에서 찾는다.
index = done.findIndex((value) => { //index 알아내기
return value.id === id;
});
done.splice(index,1);
}

console.log(todo);
console.log(done);

//변경된 상태를 react에게 알려주어야한다. 아래 코드 안쓰면 x눌러도 화면에서 안사라짐.
updateCards({
"todo" : todo,
"done":done
//todo, done
//이렇게 한줄로만 써도 된다. 똑같은것이다.
});

//updateCards 호출
// react 해당 데이터가 변경이 됐구나!
// react 해당 데이터를 사용하는 모든 컴포넌트를 부라우저에서 다시 그려준다.
} else {
alert('카드 삭제에 실패했습니다.');
}
}

return (
<div className='board'>
<div className='board-list'>
<div className="board">
<div className="board-list">
{
Object.entries(cards).map(([subject, tasks]) => {
return <Card key={subject} subject={subject} tasks={tasks} move={move}/>;
})
Object.entries(cards).map(([subject, tasks]) =>
// Object.entries(cards) : ㅏkey에 done, value에 해당값들. 즉 [todo,[{},{}]]로 만들어준다.
<Card remove={remove} key={subject} subject={subject} tasks={tasks} move={move}/>, // map(function) : function를 적용시켜서 변환
//remove={remove} : 자식한테 props로 전달해준다.
)
}
</div>

<Link className='board-link' to="/enrollment">ADD</Link>
<Link className="board-link" to="/enrollment">ADD</Link>
</div>
);
}
Expand Down
34 changes: 33 additions & 1 deletion static/src/page/Enrollment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,35 @@ import Input from "../component/atom/Input";

function Enrollment({history}) {
const [title, setTitle] = useState('');
const [assignee, setAssignee] = useState('');
const [priority, setPriority]=useState(2);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

초기화 굿굿 👍


const onChange = (event) => {
event.stopPropagation();
setTitle(event.target.value);
};

const onChangeAssignee = (event) => {
event.stopPropagation();
setAssignee(event.target.value);
};

const onChangePriority = (event) => {
event.stopPropagation();
setPriority(event.target.value);
};

function onDisplayPriority(){
document.getElementById("priority").selectedIndex="1";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리액트에서는 브라우저에서 지원하는 DOM에 직접 접근하는 방식보다 Ref 라는 방식
을 통해서 Element에 접근하는 것을 권장하고 있어.

아래 링크를 통해서도 자세한 이유를 확인할 수 있어
Ref가 document.getElementById 보다 나은 이유

(확실하진 않지만, DOM에 직접 접근하게 되면 React가 제공하는 가상 DOM의 장점을 잃게 되지 않을까..?)

Hooks API로는 useRef()를 사용할 수 있어~

const priorityEl = useRef(null);

function onDisplayPriority() {
  priorityEl.current. selectedIndex = "1";
}

return (
   ...
   <select name="priority" id="priority" onChange={onChangePriority}  ref={el}>
      ....
    </select>
   ....
);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인덱스로 <option> 지정할 수 있는 selectedIndex 프로퍼티를 제공하는구나
굿굿 👍 👍
https://www.w3schools.com/jsref/prop_select_selectedindex.asp

}

const onPreviousClick = (event) => {
event.stopPropagation();
history.goBack();
};

const add = async () => {
const isSuccesses = await createCard(title);
const isSuccesses = await createCard(title, assignee, priority);
if (isSuccesses) {
history.goBack();
} else {
Expand All @@ -41,13 +57,29 @@ function Enrollment({history}) {
const onClearClick = (event) => {
event.stopPropagation();
setTitle('');
setAssignee('');
setPriority(2);
Copy link
Collaborator

@raccoonback raccoonback Aug 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<select> 태그의 value 속성을 priority으로 설정해주면, onDisplayPriority() 메서드 없이도 setPriority(2) 호출만으로 변경이 반영될 거 같아~

const [priority, setPriority] = useState(2);
...
const onClearClick = (event) => {
  ...
  setPriority(2);
  ....
}
...

return (
   ...
    <select name="priority" id="priority" onChange={onChangePriority}  value={priority}>
      ....
    </select>
    ....
);

onDisplayPriority();

};


return (
<div className='enrollment'>
<div className='enrollment-title'>
<label htmlFor="title">Title</label>
<Input id='title' onChange={onChange} onKeyPress={onEnterPress} value={title}/>
<br/>
<label htmlFor="title">Assignee</label>
<Input id='assignee' onChange={onChangeAssignee} value={assignee}/>
<br/>
<label htmlFor="title">Priority</label>
<select name="priority" id="priority" onChange={onChangePriority}>
<option value="1">1순위</option>
<option value="2" selected="selected">2순위</option>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selected 속성 잘사용했네 굿굿 👍

<option value="3">3순위</option>
</select>

</div>
<div className='enrollment-btn-grp'>
<Button className='enrollment-btn' onClick={onPreviousClick} value='이전'/>
Expand Down
6 changes: 3 additions & 3 deletions static/src/service/createCard.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
async function createCard(title) {
async function createCard(title, assignee, priority) {
try {
const response = await fetch('/todo/cards', {
method: 'POST',
Expand All @@ -7,7 +7,7 @@ async function createCard(title) {
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
body: JSON.stringify({ title }),
body: JSON.stringify({ title, assignee, priority }),
});

return response.status === 201;
Expand All @@ -16,4 +16,4 @@ async function createCard(title) {
}
}

export default createCard;
export default createCard;
5 changes: 4 additions & 1 deletion static/src/service/getCards.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ async function getCards() {
});

const cards = await response.json();
//console.log(cards); //todo done 상관없이 출력
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

불필요한 주석 또는 콘솔 로그 삭제~

const todo = cards.filter((card) => card.status === 'TODO');
const done = cards.filter((card) => card.status === 'DONE');
return {
//console.log(todo,done);

return { //객체로 반환, ㅅtodo:[{},{}]
todo, done,
};
} catch (e) {
Expand Down
19 changes: 19 additions & 0 deletions static/src/service/removeCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
async function removeCard(id) {
try {
const response = await fetch('/todo/cards/${id}', {
method: 'DELETE',
credentials: 'include',
mode: 'cors',
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
body: JSON.stringify({ id }),
});

return response.status === 201;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

삭제 성공한 경우, status code => 204(No Content)
https://docs.google.com/document/d/18hPE1bP4o4xP9xIAbHOL5-baelotFG9_zz8uJUPPVzw/edit

} catch (e) {
return false;
}
}

export default removeCard;