diff --git a/.gitignore b/.gitignore index 20fccdd..fd07293 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ yarn-error.log* .env.development.local .env.test.local .env.production.local + +.now \ No newline at end of file diff --git a/.now/project.json b/.now/project.json index c52546c..2ec18cf 100644 --- a/.now/project.json +++ b/.now/project.json @@ -1 +1 @@ -{"orgId":"vC0ivr1sq0T0zKJytpWAmdFN","projectId":"QmU68M4LipQZeiFKBEhK7WmUX9o8wjXK3RGeuiZ8PSWDDK"} \ No newline at end of file +{"orgId":"Zo3Q3h9F77k7oPOVf5QNEp0q","projectId":"QmVYdcpYkTHLrGcnjr7PaRHw7HPc4ufUWHRCmRJ8W5de6H"} \ No newline at end of file diff --git a/README.md b/README.md index f53f3d3..4af18ad 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,22 @@ # react-todo-11th -## 실행 방법 +## 구성 파악 -``` -npm install -npm run dev -``` +1. 첫 화면에 날짜와 업무를 입력하는 부분이 있다 +2. 날짜와 업무를 입력하면 오른쪽에 투두 리스트가 쌓인다 +3. 투두 리스트에는 완료 버튼이 있고, 완료 버튼을 누르면 해당 업무가 사라진다. +4. 투두 입력과 제출시 alert으로 정해진 값 입력을 안내한다. -- npm install : 필요한 모든 패키지를 설치합니다. 처음 1번만 실행하면 됩니다. -- npm run dev : react 어플리케이션을 브라우저에서 실행합니다. +## 구현 방법 -## 배포 방법 +1. 프론트 구성(배경색, 글자크기와 색 및 위치 등) 완성 +2. index에 투두 배열 생성 후 값을 받아오고, 뿌린다 +3. index에서 TodoInput부분과 TodoList부분을 구성해놓는다 +4. TodoInput에서 받아온 배열을 TodoList로 보낸다 +5. TodoList에서 배열을 map으로 파싱하여 TodoItem으로 보내 내용을 띄운다 +6. TodoItem에서 완료 클릭 시 index에서 해당 배열을 id값으로 삭제한다 -- now에 회원가입하고 now를 설치합니다. +## 어려웠던 점 -1. https://zeit.co 에서 회원가입합니다. -2. 터미널에서 npm i -g now를 입력해 now를 글로벌로 설치합니다. -3. 명령 프롬프트에서 프로젝트 폴더에 들어간 후 now를 입력합니다. -4. ID/PW를 입력합니다. -5. zeit 가입시 입력한 이메일에서 인증 링크를 클릭합니다. <인증완료> -6. 다시 프로젝트 폴더에서 now를 입력하면 자동으로 생성된 url에 배포됩니다! - -## 미션 설명 - -[미션 설명](./docs/mission-description/README.md) - -## 미션 제출 방법 - -[미션 제출 방법](./docs/how-to-submit/README.md) +1. useState을 이용해 배열을 할당해본 경험이 없어서 원하는대로 배열 내부를 구성해서 사용하기까지 어려움이 있었습니다. +2. class형이 아닌 함수형으로 구현한 react에서 TodoItem에서 id값을 끌어오는 것이 조금 힘들었습니다. diff --git a/components/todo-input.js b/components/todo-input.js index 1844e25..387f817 100644 --- a/components/todo-input.js +++ b/components/todo-input.js @@ -1,20 +1,93 @@ import React from "react"; import styled from "styled-components"; -export default function TodoInput() { +export default function TodoInput({ + date, + task, + addTodo, + onChangeDate, + onChangeTask, +}) { return ( - 리액트-투두 -
- 시간을 입력하는 칸 -
- Todo를 입력하는 칸 + + 날짜 + + + + TODO + + + 등록
); } +const Submit = styled.button` + color: white; + background-color: rgb(97, 97, 97); + font-size: 1.5rem; + outline: none; + border-style: none; + padding: 0.5rem 1rem; + border-radius: 0.3rem; +`; +const DateLabel = styled.p` + font-size: 1.5rem; + padding: 0px; + margin: 0px; +`; +const DateInputArea = styled.input` + width: 80%; + border: 1px solid rgb(97, 97, 97); + padding: 0.5rem 0.8rem; +`; +const TodoLabel = styled.p` + font-size: 1.5rem; + padding: 0px; + margin: 0px; +`; +const TaskTextArea = styled.textarea` + width: 80%; + height: 30vh; + resize: none; + border: 1px solid rgb(97, 97, 97); + padding: 0.5rem 0.8rem; +`; +const DateInput = styled.div` + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 3rem; +`; + +const TaskInput = styled.div` + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 3rem; +`; + const Wrapper = styled.div` - border: solid 1px; - font-size: 18px; - flex: 1; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + height: 37rem; + flex: 1 1 0%; + border: 1px solid black; + padding: 1rem 2rem; `; diff --git a/components/todo-item.js b/components/todo-item.js index ef2dbe8..0ca1f64 100644 --- a/components/todo-item.js +++ b/components/todo-item.js @@ -1,11 +1,46 @@ import React from "react"; import styled from "styled-components"; -export default function TodoItem() { - return Todo; +export default function TodoItem({ id, task, date, onClickComplete }) { + return ( + + {task} + + {date} + onClickComplete(id)}>완료 + + + ); } - +const Complete = styled.button` + color: white; + background-color: rgb(97, 97, 97); + font-size: 1.5rem; + outline: none; + padding: 0.5rem 1rem; + border-radius: 0.3rem; +`; +const CompleteSection = styled.p` + font-size: 1.5rem; + display: flex; + flex-direction: column; + padding: 0px; + margin: 0px; +`; +const TodoContents = styled.p` + font-size: 1.5rem; + display: flex; + flex-direction: column; + padding: 0px; + margin: 0px; +`; const Wrapper = styled.div` - font-size: 18px; - border: solid 1px; + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 3rem; + padding: 1rem 2rem; + border: 1px solid rgb(97, 97, 97); `; diff --git a/components/todo-list.js b/components/todo-list.js index 68fded1..0571e5b 100644 --- a/components/todo-list.js +++ b/components/todo-list.js @@ -3,17 +3,17 @@ import styled from "styled-components"; import TodoItem from "./todo-item"; -export default function TodoList() { +export default function TodoList({ todos, onClickComplete }) { return ( - Todo list가 들어가는 자리입니다! - + {todos.map((todo) => ( + + ))} ); } const Wrapper = styled.div` - border: solid 1px; font-size: 18px; - flex: 1; + flex: 1 1 0%; `; diff --git a/pages/index.js b/pages/index.js index f494909..978da00 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState } from "react"; import TodoInput from "../components/todo-input"; import TodoList from "../components/todo-list"; @@ -6,25 +6,93 @@ import TodoList from "../components/todo-list"; import styled from "styled-components"; export default function Home() { + const [date, setDate] = useState(); + const [task, setTask] = useState(); + const [todos, setTodoList] = useState([]); + + const onChangeTask = (e) => { + setTask(e.target.value); + }; + const onChangeDate = (e) => { + setDate(e.target.value); + }; + + const stateReset = (e) => { + setDate(""); + setTask(""); + }; + + const validateTodo = () => { + let isValid = false; + let isDateValid = date.length === 8 && date > 20200101; + let isTaskValid = task.length > 0; + if (!isDateValid) { + alert("날짜를 올바른 형식으로 입력해주세요!"); + } else if (!isTaskValid) { + alert("모든 항목을 입력해주세요!"); + } + isValid = isDateValid && isTaskValid; + return isValid; + }; + + const addTodo = (e) => { + if (!validateTodo()) return; + setTodoList([ + ...todos, + { + id: todos.length, + date, + task, + }, + ]); + stateReset(e); + alert("입력 완료!"); + }; + + const onClickComplete = (id) => { + const newTodos = [...todos]; + setTodoList(newTodos.filter((todo) => todo.id !== id)); + console.log(newTodos); + }; + return ( + 리액트-투두 - - + + + ); } +const BlankSpace = styled.div` + flex: 0.3; +`; +const Title = styled.p` + font-size: 3rem; + font-weight: 600; + padding: 0px; + margin: 0px 0px 3rem; +`; const Wrapper = styled.div` - height: 100vh; + min-height: 100vh; + background-color: rgb(155, 197, 195); + padding: 4rem 5rem; + font-size: 0.1rem; + color: white; `; const Contents = styled.div` - border: solid 1px black; display: flex; flex-direction: row; justify-content: space-between; - padding: 10px 20px; - margin: 20px 10px; `;