From 191725fbe1b20f0a42fa92cdb42a59f7d93398ac Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Sun, 1 Sep 2024 23:54:03 +0900 Subject: [PATCH 01/12] =?UTF-8?q?Chore=20:=20ignore=20css=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eslint.config.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 238d2e4..a4caa38 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,8 +1,8 @@ -import js from '@eslint/js' -import globals from 'globals' -import react from 'eslint-plugin-react' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' +import js from '@eslint/js'; +import globals from 'globals'; +import react from 'eslint-plugin-react'; +import reactHooks from 'eslint-plugin-react-hooks'; +import reactRefresh from 'eslint-plugin-react-refresh'; export default [ { ignores: ['dist'] }, @@ -35,4 +35,9 @@ export default [ ], }, }, -] + { + rules: { + 'react/no-unknown-property': ['error', { ignore: ['css'] }], + }, + }, +]; From dcd69b63b40b4185638c31b4404f3dfad4747197 Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Sun, 1 Sep 2024 23:55:09 +0900 Subject: [PATCH 02/12] =?UTF-8?q?Chore=20:=20emotion/react=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index 9f1bcb2..9d862e9 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "preview": "vite preview" }, "dependencies": { + "@emotion/react": "^11.13.3", + "normalize.css": "^8.0.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, From 1ffb7cd27efdfc987f7c24a6b6b8b21a9374e786 Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Sun, 1 Sep 2024 23:56:48 +0900 Subject: [PATCH 03/12] =?UTF-8?q?Feat=20:=20UI=20=EC=9E=91=EC=84=B1=20?= =?UTF-8?q?=EB=B0=8F=20CSS=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/src/App.jsx b/src/App.jsx index 852a9fe..10df62d 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,135 @@ +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; +import 'normalize.css'; + function App() { - return
React Todo
; + const bodyStyle = css` + margin: 0; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + background-image: linear-gradient( + to bottom right, + rgb(247, 196, 218), + rgb(239, 239, 239) + ); + `; + + const containerStyle = css` + width: 350px; + height: 600px; + background-color: white; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + border-radius: 20px; + padding: 20px; + `; + + const mainTitleStyle = css` + @font-face { + font-family: 'LINESeedKR-Bd'; + src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/LINESeedKR-Bd.woff2') + format('woff2'); + font-weight: 700; + font-style: normal; + } + font-family: 'LINESeedKR-Bd'; + color: rgb(59, 56, 56); + `; + + const formStyle = css` + display: flex; + align-items: center; + `; + + const inputStyle = css` + width: 300px; + height: 35px; + outline: none; + border-radius: 20px; + border: 1.2px solid; + border-color: rgb(247, 196, 218); + padding-left: 12px; + @font-face { + font-family: 'LINESeedKR-Rg'; + src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/LINESeedKR-Rg.woff2') + format('woff2'); + font-weight: 400; + font-style: normal; + } + font-family: 'LINESeedKR-Rg'; + font-size: 12px; + color: #3d3d3d; + `; + + const addButtonStyle = css` + border: 0; + background-color: white; + font-size: 20px; + color: rgb(59, 56, 56); + margin-left: 8px; + cursor: pointer; + &:hover { + color: rgb(247, 196, 218); + } + `; + + const listStyle = css` + width: 100%; + height: 200px; + `; + + const titleStyle = css` + width: 100%; + height: 30px; + border-top: 1px solid; + border-color: rgb(247, 196, 218); + padding-top: 15px; + margin-top: 20px; + @font-face { + font-family: 'LINESeedKR-Bd'; + src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/LINESeedKR-Bd.woff2') + format('woff2'); + font-weight: 700; + font-style: normal; + } + font-family: 'LINESeedKR-Bd'; + font-size: 16px; + color: rgb(59, 56, 56); + `; + + return ( +
+
+

+ To Do List +

+
+ + +
+
+
+ 📂 TO DO (0) +
+
+
+
+
+ 🗑️ DONE (0) +
+
+
+
+
+ ); } export default App; From a0feae0a97945243c1f5cd612601713707d24cb0 Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Mon, 2 Sep 2024 15:40:24 +0900 Subject: [PATCH 04/12] =?UTF-8?q?Chore=20:=20prop-types=20=EC=84=A4?= =?UTF-8?q?=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 9d862e9..055524b 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "@emotion/react": "^11.13.3", "normalize.css": "^8.0.1", + "prop-types": "^15.8.1", "react": "^18.3.1", "react-dom": "^18.3.1" }, From bce271d7ca898e51385615113a044d02a6046b43 Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Mon, 2 Sep 2024 15:47:09 +0900 Subject: [PATCH 05/12] =?UTF-8?q?Feat=20:=20=EC=B6=94=EA=B0=80,=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C,=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/InputBox.jsx | 106 +++++++++++++++++++++++++++++ src/components/ToDoItem.jsx | 115 ++++++++++++++++++++++++++++++++ src/components/ToDoItemList.jsx | 83 +++++++++++++++++++++++ 3 files changed, 304 insertions(+) create mode 100644 src/components/InputBox.jsx create mode 100644 src/components/ToDoItem.jsx create mode 100644 src/components/ToDoItemList.jsx diff --git a/src/components/InputBox.jsx b/src/components/InputBox.jsx new file mode 100644 index 0000000..b03b3a5 --- /dev/null +++ b/src/components/InputBox.jsx @@ -0,0 +1,106 @@ +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; +import 'normalize.css'; +import { useRef, useState } from 'react'; +import PropTypes from 'prop-types'; + +export default function InputBox({ todoList, setTodoList }) { + const formStyle = css` + display: flex; + align-items: center; + `; + + const inputStyle = css` + width: 300px; + height: 35px; + outline: none; + border-radius: 20px; + border: 1.2px solid; + border-color: rgb(247, 196, 218); + padding-left: 12px; + @font-face { + font-family: 'LINESeedKR-Rg'; + src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/LINESeedKR-Rg.woff2') + format('woff2'); + font-weight: 400; + font-style: normal; + } + font-family: 'LINESeedKR-Rg'; + font-size: 12px; + color: #3d3d3d; + `; + + const addButtonStyle = css` + border: 0; + background-color: white; + font-size: 20px; + color: rgb(59, 56, 56); + margin-left: 8px; + cursor: pointer; + &:hover { + color: rgb(247, 196, 218); + } + `; + + const [text, setText] = useState(''); + const inputRef = useRef(null); + + // form 제출 시 새로고침 방지 + const formClickEvent = (e) => { + e.preventDefault(); + }; + + // input 값 가져오기 + function onChangeInput(e) { + setText(e.target.value); + //e.target에 있는 으로부터 value 값을 가져옴 + } + + function onClickButton() { + //todoItemList에 값 추가 + const AddTodoList = todoList.concat({ + id: todoList.length, + text, + checked: false, + }); + setTodoList(AddTodoList); + + setText(''); //input 값 초기화 + inputRef.current.focus(); // 버튼 누른 후 자동 포커싱 + } + + return ( +
+
+ + +
+
+ ); +} + +// props 값 검증 +InputBox.propTypes = { + todoList: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number.isRequired, + text: PropTypes.string.isRequired, + }).isRequired + ), + setTodoList: PropTypes.func.isRequired, +}; diff --git a/src/components/ToDoItem.jsx b/src/components/ToDoItem.jsx new file mode 100644 index 0000000..df3c069 --- /dev/null +++ b/src/components/ToDoItem.jsx @@ -0,0 +1,115 @@ +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; +import 'normalize.css'; +import PropTypes from 'prop-types'; + +export default function ToDoItem({ todoItem, todoList, setTodoList }) { + const spanStyle = css` + @font-face { + font-family: 'LINESeedKR-Rg'; + src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/LINESeedKR-Rg.woff2') + format('woff2'); + font-weight: 400; + font-style: normal; + } + font-family: 'LINESeedKR-Rg'; + font-size: 15px; + `; + + const spanCheckedStyle = css` + @font-face { + font-family: 'LINESeedKR-Rg'; + src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/LINESeedKR-Rg.woff2') + format('woff2'); + font-weight: 400; + font-style: normal; + } + font-family: 'LINESeedKR-Rg'; + font-size: 15px; + color: gray; + text-decoration: line-through; + `; + + const checkBoxStyle = css` + cursor: pointer; + appearance: none; + width: 12px; + height: 12px; + margin-right: 10px; + border: 1px solid; + border-radius: 10px; + + &:checked { + border-color: transparent; + background-size: 100% 100%; + background-color: rgb(247, 196, 218); + } + `; + + const deleteButtonStyle = css` + border: 0; + background-color: white; + font-size: 14px; + color: rgb(59, 56, 56); + margin-left: 8px; + cursor: pointer; + &:hover { + color: rgb(247, 196, 218); + } + `; + + function onChangeCheckbox() { + const AddTodoList = todoList.map((item) => ({ + ...item, + checked: item.id === todoItem.id ? !item.checked : item.checked, + })); + setTodoList(AddTodoList); + } + + function onDelete(id) { + setTodoList(todoList.filter((todoItem) => todoItem.id !== id)); + } + + return ( +
  • + + + {todoItem.text} + + +
  • + ); +} + +ToDoItem.propTypes = { + todoItem: PropTypes.shape({ + id: PropTypes.number, + text: PropTypes.string.isRequired, + checked: PropTypes.bool.isRequired, + }), + todoList: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number.isRequired, + text: PropTypes.string.isRequired, + checked: PropTypes.bool.isRequired, + }) + ), + setTodoList: PropTypes.func.isRequired, +}; diff --git a/src/components/ToDoItemList.jsx b/src/components/ToDoItemList.jsx new file mode 100644 index 0000000..3ae6b9f --- /dev/null +++ b/src/components/ToDoItemList.jsx @@ -0,0 +1,83 @@ +/** @jsxImportSource @emotion/react */ +import { css } from '@emotion/react'; +import 'normalize.css'; +import ToDoItem from './ToDoItem'; +import PropTypes from 'prop-types'; + +export default function ToDoItemList({ + title, + todoList, + setTodoList, + checkedList, +}) { + const titleStyle = css` + width: 100%; + height: 30px; + border-top: 1px solid; + border-color: rgb(247, 196, 218); + padding-top: 15px; + margin-top: 20px; + @font-face { + font-family: 'LINESeedKR-Bd'; + src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/LINESeedKR-Bd.woff2') + format('woff2'); + font-weight: 700; + font-style: normal; + } + font-family: 'LINESeedKR-Bd'; + font-size: 16px; + color: rgb(59, 56, 56); + `; + + const listStyle = css` + width: 100%; + height: 180px; + `; + + const ulStyle = css` + list-style: none; + display: flex; + flex-direction: column; + justify-content: center; + padding-left: 10px; + `; + + return ( +
    +
    + {title} +
    +
    +
      + {todoList && + todoList.map((todoItem) => { + // checkedList 값에 따라 'TO DO 목록' 또는 'DONE 목록' 출력 + if (checkedList !== todoItem.checked) return null; + return ( + // 각각의 todoItem 출력 + + ); + })} +
    +
    +
    + ); +} + +ToDoItemList.propTypes = { + title: PropTypes.string.isRequired, + todoList: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number.isRequired, + text: PropTypes.string.isRequired, + checked: PropTypes.bool.isRequired, + }) + ), + setTodoList: PropTypes.func.isRequired, + checkedList: PropTypes.bool.isRequired, +}; From 7adec985c9887f45c08963ffc1b47b12c15c8c98 Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Mon, 2 Sep 2024 15:49:50 +0900 Subject: [PATCH 06/12] =?UTF-8?q?Refactor=20:=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=EB=B3=84=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 104 +++++++++++----------------------------------------- 1 file changed, 21 insertions(+), 83 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 10df62d..aeef1ac 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,9 @@ /** @jsxImportSource @emotion/react */ import { css } from '@emotion/react'; import 'normalize.css'; +import { useState } from 'react'; +import InputBox from './components/InputBox.jsx'; +import ToDoItemList from './components/ToDoItemList.jsx'; function App() { const bodyStyle = css` @@ -37,66 +40,7 @@ function App() { color: rgb(59, 56, 56); `; - const formStyle = css` - display: flex; - align-items: center; - `; - - const inputStyle = css` - width: 300px; - height: 35px; - outline: none; - border-radius: 20px; - border: 1.2px solid; - border-color: rgb(247, 196, 218); - padding-left: 12px; - @font-face { - font-family: 'LINESeedKR-Rg'; - src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/LINESeedKR-Rg.woff2') - format('woff2'); - font-weight: 400; - font-style: normal; - } - font-family: 'LINESeedKR-Rg'; - font-size: 12px; - color: #3d3d3d; - `; - - const addButtonStyle = css` - border: 0; - background-color: white; - font-size: 20px; - color: rgb(59, 56, 56); - margin-left: 8px; - cursor: pointer; - &:hover { - color: rgb(247, 196, 218); - } - `; - - const listStyle = css` - width: 100%; - height: 200px; - `; - - const titleStyle = css` - width: 100%; - height: 30px; - border-top: 1px solid; - border-color: rgb(247, 196, 218); - padding-top: 15px; - margin-top: 20px; - @font-face { - font-family: 'LINESeedKR-Bd'; - src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_11-01@1.0/LINESeedKR-Bd.woff2') - format('woff2'); - font-weight: 700; - font-style: normal; - } - font-family: 'LINESeedKR-Bd'; - font-size: 16px; - color: rgb(59, 56, 56); - `; + const [todoList, setTodoList] = useState([]); //todoItem을 담을 리스트 return (
    @@ -104,29 +48,23 @@ function App() {

    To Do List

    -
    - - -
    -
    -
    - 📂 TO DO (0) -
    -
    -
    -
    -
    - 🗑️ DONE (0) -
    -
    -
    + + + {/* 할 일 목록 */} + + + {/* 완료된 목록 */} +
    ); From 2ebb7b29189e08b89cc4d2aee4d8d17c1bb15a05 Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Mon, 2 Sep 2024 16:26:42 +0900 Subject: [PATCH 07/12] =?UTF-8?q?Style=20:=20=EC=84=B8=EB=AF=B8=20?= =?UTF-8?q?=EC=BD=9C=EB=A1=A0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.jsx b/src/main.jsx index 3d9da8a..224ec06 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,9 +1,9 @@ -import { StrictMode } from 'react' -import { createRoot } from 'react-dom/client' -import App from './App.jsx' +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './App.jsx'; createRoot(document.getElementById('root')).render( - , -) + +); From 773ed2f71a9d361276775f1f60392cab943b0bfe Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Tue, 3 Sep 2024 15:48:24 +0900 Subject: [PATCH 08/12] =?UTF-8?q?Feat=20:=20localStorage=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EC=97=AC=20todoList=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=EC=83=81=ED=83=9C=20=EC=84=A4=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index aeef1ac..6e53059 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import { css } from '@emotion/react'; import 'normalize.css'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import InputBox from './components/InputBox.jsx'; import ToDoItemList from './components/ToDoItemList.jsx'; @@ -40,7 +40,16 @@ function App() { color: rgb(59, 56, 56); `; - const [todoList, setTodoList] = useState([]); //todoItem을 담을 리스트 + // 초기 상태를 localStorage에서 불러옴 + const [todoList, setTodoList] = useState(() => { + const savedTodoList = localStorage.getItem('todoList'); + return savedTodoList ? JSON.parse(savedTodoList) : []; + }); + + // todoList가 업데이트될 때마다 localStorage에 저장 + useEffect(() => { + localStorage.setItem('todoList', JSON.stringify(todoList)); + }, [todoList]); return (
    @@ -48,11 +57,14 @@ function App() {

    To Do List

    + {/* 할 일 입력 */} {/* 할 일 목록 */} !item.checked).length + })`} // 아직 완료되지 않은목록의 길이 todoList={todoList} setTodoList={setTodoList} checkedList={false} @@ -60,7 +72,7 @@ function App() { {/* 완료된 목록 */} item.checked).length})`} // 완료된 목록의 길이 todoList={todoList} setTodoList={setTodoList} checkedList={true} From 701732739019c89cbbcea86f56b6f5f61aa60dc8 Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Tue, 3 Sep 2024 15:50:57 +0900 Subject: [PATCH 09/12] =?UTF-8?q?Feat=20:=20autoFocus=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/InputBox.jsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/components/InputBox.jsx b/src/components/InputBox.jsx index b03b3a5..b0e048f 100644 --- a/src/components/InputBox.jsx +++ b/src/components/InputBox.jsx @@ -42,7 +42,7 @@ export default function InputBox({ todoList, setTodoList }) { } `; - const [text, setText] = useState(''); + const [text, setText] = useState(''); // input에 입력한 값 const inputRef = useRef(null); // form 제출 시 새로고침 방지 @@ -53,11 +53,15 @@ export default function InputBox({ todoList, setTodoList }) { // input 값 가져오기 function onChangeInput(e) { setText(e.target.value); - //e.target에 있는 으로부터 value 값을 가져옴 + // e.target에 있는 으로부터 value 값을 가져옴 } + // + 버튼 클릭(form 제출) function onClickButton() { - //todoItemList에 값 추가 + // 공백 입력 방지 + if (text.trim() === '') return; + + // todoItemList에 값 추가 const AddTodoList = todoList.concat({ id: todoList.length, text, @@ -65,8 +69,8 @@ export default function InputBox({ todoList, setTodoList }) { }); setTodoList(AddTodoList); - setText(''); //input 값 초기화 - inputRef.current.focus(); // 버튼 누른 후 자동 포커싱 + setText(''); // input 값 초기화 + inputRef.current.focus(); // 버튼 누른 후에도 input box에 자동 포커싱 } return ( @@ -79,8 +83,9 @@ export default function InputBox({ todoList, setTodoList }) { ref={inputRef} className="input-box" placeholder="할일을 입력하세요" - onChange={onChangeInput} //input 값이 변하면(이벤트 발생) 메소드 실행 + onChange={onChangeInput} // input 값이 변하면(이벤트 발생) 메소드 실행 css={inputStyle} + autoFocus />
      + {/* todoList에 값이 있을 경우에만 실행 */} {todoList && todoList.map((todoItem) => { // checkedList 값에 따라 'TO DO 목록' 또는 'DONE 목록' 출력 From 91f365f1c18709f737ba3f0c833cb24c57995a46 Mon Sep 17 00:00:00 2001 From: Yoonjeong Ko Date: Tue, 3 Sep 2024 15:55:30 +0900 Subject: [PATCH 11/12] =?UTF-8?q?Design=20:=20text=20color=20=20=EC=88=98?= =?UTF-8?q?=EC=A0=95,=20li=20=ED=83=9C=EA=B7=B8=20margin=20=EA=B0=92=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20checkBox=20border-color=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ToDoItem.jsx | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/components/ToDoItem.jsx b/src/components/ToDoItem.jsx index df3c069..3a59905 100644 --- a/src/components/ToDoItem.jsx +++ b/src/components/ToDoItem.jsx @@ -14,6 +14,7 @@ export default function ToDoItem({ todoItem, todoList, setTodoList }) { } font-family: 'LINESeedKR-Rg'; font-size: 15px; + color: rgb(59, 56, 56); `; const spanCheckedStyle = css` @@ -30,6 +31,10 @@ export default function ToDoItem({ todoItem, todoList, setTodoList }) { text-decoration: line-through; `; + const liStyle = css` + margin: 3px 0px 3px 0px; + `; + const checkBoxStyle = css` cursor: pointer; appearance: none; @@ -38,6 +43,7 @@ export default function ToDoItem({ todoItem, todoList, setTodoList }) { margin-right: 10px; border: 1px solid; border-radius: 10px; + border-color: rgb(59, 56, 56); &:checked { border-color: transparent; @@ -51,27 +57,32 @@ export default function ToDoItem({ todoItem, todoList, setTodoList }) { background-color: white; font-size: 14px; color: rgb(59, 56, 56); - margin-left: 8px; + margin-left: 3px; cursor: pointer; &:hover { color: rgb(247, 196, 218); } `; + // checkbox를 클릭하면, todoItem의 checked 값이 토글됨 function onChangeCheckbox() { - const AddTodoList = todoList.map((item) => ({ + const updatedTodoList = todoList.map((item) => ({ ...item, checked: item.id === todoItem.id ? !item.checked : item.checked, })); - setTodoList(AddTodoList); + + setTodoList(updatedTodoList); } + // 항목 삭제 function onDelete(id) { - setTodoList(todoList.filter((todoItem) => todoItem.id !== id)); + // 주어진 id와 일치하지 않는 항목들만 남김(일치하면 필터링 -> 해당 항목 삭제) + const updatedTodoList = todoList.filter((todoItem) => todoItem.id !== id); + setTodoList(updatedTodoList); } return ( -
    • +
    • Date: Wed, 4 Sep 2024 10:24:56 +0900 Subject: [PATCH 12/12] =?UTF-8?q?Design=20:=20scroll=20style=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ToDoItemList.jsx | 56 ++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/src/components/ToDoItemList.jsx b/src/components/ToDoItemList.jsx index 77c7630..24f019c 100644 --- a/src/components/ToDoItemList.jsx +++ b/src/components/ToDoItemList.jsx @@ -10,6 +10,18 @@ export default function ToDoItemList({ setTodoList, checkedList, }) { + const listBoxStyle = css` + overflow-y: auto; + &::-webkit-scrollbar { + // 스크롤바 모양 변경 + width: 4px; + } + &::-webkit-scrollbar-thumb { + border-radius: 2px; // 스크롤바 모서리 둥글게 + background: rgb(255, 238, 245); // 스크롤바 색상 변경 + } + `; + const titleStyle = css` width: 100%; height: 30px; @@ -44,30 +56,32 @@ export default function ToDoItemList({ `; return ( -
      + <>
      {title}
      -
      -
        - {/* todoList에 값이 있을 경우에만 실행 */} - {todoList && - todoList.map((todoItem) => { - // checkedList 값에 따라 'TO DO 목록' 또는 'DONE 목록' 출력 - if (checkedList !== todoItem.checked) return null; - return ( - // 각각의 todoItem 출력 - - ); - })} -
      -
      -
      +
      +
      +
        + {/* todoList에 값이 있을 경우에만 실행 */} + {todoList && + todoList.map((todoItem) => { + // checkedList 값에 따라 'TO DO 목록' 또는 'DONE 목록' 출력 + if (checkedList !== todoItem.checked) return null; + return ( + // 각각의 todoItem 출력 + + ); + })} +
      +
      +
      + ); }