From 6f490a5ed960a29e13fbfc8b2e40f65f47399568 Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 18:38:27 +0900 Subject: [PATCH 01/12] =?UTF-8?q?Docs:=20=EA=B5=AC=ED=98=84=ED=95=A0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EB=AA=A9=EB=A1=9D=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c0710d2..5c155071 100644 --- a/README.md +++ b/README.md @@ -1 +1,36 @@ -# react-todo-list-precourse \ No newline at end of file +# πŸ“– ν•  일 λͺ©λ‘ - λ―Έλ‹ˆκ³Όμ œ + +## 과제 μ§„ν–‰ μš”κ΅¬ 사항 βœ… + +- [x] λ―Έμ…˜μ€ ν•  일 λͺ©λ‘ μ €μž₯μ†Œλ₯Ό ν¬ν¬ν•˜κ³  ν΄λ‘ ν•˜λŠ” κ²ƒμœΌλ‘œ μ‹œμž‘ν•œλ‹€. +- [x] κΈ°λŠ₯을 κ΅¬ν˜„ν•˜κΈ° μ „ README.md 에 κ΅¬ν˜„ν•  κΈ°λŠ₯ λͺ©λ‘μ„ 정리해 μΆ”κ°€ν•œλ‹€. +- [x] Git의 컀밋 λ‹¨μœ„λŠ” μ•ž λ‹¨κ³„μ—μ„œ README.md 에 μ •λ¦¬ν•œ κΈ°λŠ₯ λͺ©λ‘ λ‹¨μœ„λ‘œ μΆ”κ°€ν•œλ‹€. + +## πŸš€ κΈ°λŠ₯ μš”κ΅¬ 사항 βœ… + +ν•˜λ£¨ λ˜λŠ” ν•œ 주의 ν•  일 λͺ©λ‘μ„ μ—…λ°μ΄νŠΈν•˜λŠ” ν•  일 λͺ©λ‘μ„ κ΅¬ν˜„ν•œλ‹€. **React 라이브러리λ₯Ό μ‚¬μš©ν•˜μ—¬ μ›Ή μ•±μœΌλ‘œ κ΅¬ν˜„ν•œλ‹€.** + +- [ ] ν•  일을 μΆ”κ°€ν•˜κ³  μ‚­μ œν•  수 μžˆλ‹€. +- [ ] ν•  일을 μΆ”κ°€ν•  λ•Œ μ‚¬μš©μžλŠ” Enter ν‚€λ‚˜ μΆ”κ°€ λ²„νŠΌμ„ μ‚¬μš©ν•˜μ—¬ ν•  일을 λͺ©λ‘μ— μΆ”κ°€ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€. +- [ ] μ‚¬μš©μžκ°€ 아무것도 μž…λ ₯ν•˜μ§€ μ•Šμ€ κ²½μš°μ—λŠ” ν•  일을 μΆ”κ°€ν•  수 μ—†λ‹€. +- [ ] ν•  일의 λͺ©λ‘μ„ λ³Ό 수 μžˆλ‹€. +- [ ] ν•  일의 μ™„λ£Œ μƒνƒœλ₯Ό μ „ν™˜ν•  수 μžˆλ‹€. + +## πŸš€ 선택 μš”κ΅¬ 사항 βœ… + +- [ ] ν˜„μž¬ μ§„ν–‰ 쀑인 ν•  일, μ™„λ£Œλœ ν•  일, λͺ¨λ“  ν•  일을 필터링할 수 μžˆλ‹€. +- [ ] ν•΄μ•Ό ν•  일의 총개수λ₯Ό 확인할 수 μžˆλ‹€. +- [ ] μƒˆλ‘œκ³ μΉ¨μ„ ν•˜μ—¬λ„ 이전에 μž‘μ„±ν•œ λ°μ΄ν„°λŠ” μœ μ§€λ˜μ–΄μ•Ό ν•œλ‹€. + +## 🎯 주의 ν•΄μ•Ό ν•  ν”„λ‘œκ·Έλž˜λ° μš”κ΅¬ 사항 βœ… + +- [ ] ν”„λ‘œκ·Έλž¨ μ‹€ν–‰μ˜ μ‹œμž‘μ μ€ App.js 이닀. +- [ ] package.json νŒŒμΌμ€ λ³€κ²½ν•  수 μ—†μœΌλ©°, 제곡된 λΌμ΄λΈŒλŸ¬λ¦¬μ™€ μŠ€νƒ€μΌ 라이브러리 μ΄μ™Έμ˜ μ™ΈλΆ€ λΌμ΄λΈŒλŸ¬λ¦¬λŠ” μ‚¬μš©ν•˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€. +- [ ] ν”„λ‘œκ·Έλž¨ μ’…λ£Œ μ‹œ process.exit() λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•ŠλŠ”λ‹€. +- [ ] indent(인덴트, λ“€μ—¬μ“°κΈ°) depthλ₯Ό 3이 λ„˜μ§€ μ•Šλ„λ‘ κ΅¬ν˜„ν•œλ‹€. 2κΉŒμ§€λ§Œ ν—ˆμš©ν•œλ‹€. +- [ ] ν•¨μˆ˜(λ˜λŠ” λ©”μ„œλ“œ)의 길이가 15라인을 λ„˜μ–΄κ°€μ§€ μ•Šλ„λ‘ κ΅¬ν˜„ν•œλ‹€. + +### 과제 제좜 μ „ 체크리슀트 + +- [ ] ν„°λ―Έλ„μ—μ„œ node --version 을 μ‹€ν–‰ν•˜μ—¬ Node.js 버전이 18.17.1 이상인지 ν™•μΈν•œλ‹€. +- [ ] npm install , npm run start λͺ…λ Ή μž…λ ₯ν•˜μ—¬ νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜ν•œ ν›„ μ‹€ν–‰ν•˜λŠ” 데 λ¬Έμ œκ°€ μ—†μ–΄μ•Ό ν•œλ‹€. From ada1057d929cf4f503cde189af41adf7b8964757 Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 20:00:42 +0900 Subject: [PATCH 02/12] =?UTF-8?q?Refactor:=20jsx=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EB=B0=8F=20id=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index b021b5c8..351ba609 100644 --- a/index.html +++ b/index.html @@ -1,12 +1,12 @@ - - + + -
- +
+ From eb157784bf37b2fd67bf0f88dccf8097bac55a66 Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 20:03:58 +0900 Subject: [PATCH 03/12] =?UTF-8?q?Refactor:=20render=20=EB=B6=80=EB=B6=84?= =?UTF-8?q?=20main=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.js | 0 src/main.jsx | 10 ++++++++++ 2 files changed, 10 insertions(+) delete mode 100644 src/main.js create mode 100644 src/main.jsx diff --git a/src/main.js b/src/main.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 00000000..8db5acb8 --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,10 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; + +const root = ReactDOM.createRoot(document.getElementById("root")); +root.render( + + + +); From f7268afeade7964f72e7d911f522ae82b405d7d8 Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 20:08:04 +0900 Subject: [PATCH 04/12] =?UTF-8?q?Feat:=20Todo=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.css | 4 ++++ src/App.jsx | 13 +++++++++++++ src/components/TodoBox.jsx | 8 ++++++++ src/styles/TodoBox.css | 13 +++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 src/App.css create mode 100644 src/App.jsx create mode 100644 src/components/TodoBox.jsx create mode 100644 src/styles/TodoBox.css diff --git a/src/App.css b/src/App.css new file mode 100644 index 00000000..dc38fea7 --- /dev/null +++ b/src/App.css @@ -0,0 +1,4 @@ +/* App.css */ +body { + background: #d3d3d3; +} diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 00000000..334fed67 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,13 @@ +import React from "react"; +import TodoBox from "./components/TodoBox"; +import "./App.css"; + +function App() { + return ( + <> + μ•ˆλ…•ν•˜μ„Έμš” + + ); +} + +export default App; diff --git a/src/components/TodoBox.jsx b/src/components/TodoBox.jsx new file mode 100644 index 00000000..0eebb760 --- /dev/null +++ b/src/components/TodoBox.jsx @@ -0,0 +1,8 @@ +import React from "react"; +import "../styles/TodoBox.css"; + +function TodoBox({ children }) { + return
{children}
; +} + +export default TodoBox; diff --git a/src/styles/TodoBox.css b/src/styles/TodoBox.css new file mode 100644 index 00000000..202d17ad --- /dev/null +++ b/src/styles/TodoBox.css @@ -0,0 +1,13 @@ +.todo-box { + width: 512px; + height: 768px; + position: relative; + background: white; + border-radius: 16px; + box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.04); + margin: 0 auto; + margin-top: 96px; + margin-bottom: 32px; + display: flex; + flex-direction: column; +} From 6bc79a957aa0098514efd04564b84a88a1373650 Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 20:22:44 +0900 Subject: [PATCH 05/12] =?UTF-8?q?Feat:=20Todo-Head=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 5 ++++- src/components/TodoHead.jsx | 14 ++++++++++++++ src/styles/TodoHead.css | 26 ++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/components/TodoHead.jsx create mode 100644 src/styles/TodoHead.css diff --git a/src/App.jsx b/src/App.jsx index 334fed67..2e322a77 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,11 +1,14 @@ import React from "react"; import TodoBox from "./components/TodoBox"; +import TodoHead from "./components/TodoHead"; import "./App.css"; function App() { return ( <> - μ•ˆλ…•ν•˜μ„Έμš” + + + ); } diff --git a/src/components/TodoHead.jsx b/src/components/TodoHead.jsx new file mode 100644 index 00000000..327a1386 --- /dev/null +++ b/src/components/TodoHead.jsx @@ -0,0 +1,14 @@ +import React from "react"; +import "../styles/TodoHead.css"; + +function TodoHead() { + return ( +
+

2024λ…„ 6μ›” 9일

+
μΌμš”μΌ
+
ν•  일 2개 λ‚¨μŒ
+
+ ); +} + +export default TodoHead; diff --git a/src/styles/TodoHead.css b/src/styles/TodoHead.css new file mode 100644 index 00000000..6c2e19e8 --- /dev/null +++ b/src/styles/TodoHead.css @@ -0,0 +1,26 @@ +.todo-head-block { + padding-top: 48px; + padding-left: 32px; + padding-right: 32px; + padding-bottom: 24px; + border-bottom: 1px solid #e9ecef; +} + +.todo-head-block h1 { + margin: 0; + font-size: 36px; + color: #343a40; +} + +.todo-head-block .day { + margin-top: 4px; + color: #868e96; + font-size: 21px; +} + +.todo-head-block .tasks-left { + color: #20c997; + font-size: 18px; + margin-top: 40px; + font-weight: bold; +} From e77bb8f45d7eba984d0c3e39274225cb82248855 Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 21:08:24 +0900 Subject: [PATCH 06/12] =?UTF-8?q?Feat:=20TodoList=EC=99=80=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=20Item=20=EB=B0=8F=20check,delete=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/App.jsx | 4 ++- src/components/TodoItem.jsx | 20 +++++++++++++ src/components/TodoList.jsx | 16 ++++++++++ src/images/delete.png | Bin 0 -> 17727 bytes src/images/done.png | Bin 0 -> 6723 bytes src/styles/TodoItem.css | 57 ++++++++++++++++++++++++++++++++++++ src/styles/TodoList.css | 6 ++++ 7 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/components/TodoItem.jsx create mode 100644 src/components/TodoList.jsx create mode 100644 src/images/delete.png create mode 100644 src/images/done.png create mode 100644 src/styles/TodoItem.css create mode 100644 src/styles/TodoList.css diff --git a/src/App.jsx b/src/App.jsx index 2e322a77..6b4e430b 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,13 +1,15 @@ import React from "react"; import TodoBox from "./components/TodoBox"; import TodoHead from "./components/TodoHead"; +import TodoList from "./components/TodoList"; import "./App.css"; function App() { return ( <> - + + ); diff --git a/src/components/TodoItem.jsx b/src/components/TodoItem.jsx new file mode 100644 index 00000000..06c72b99 --- /dev/null +++ b/src/components/TodoItem.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import "../styles/TodoItem.css"; +import doneImage from "../images/done.png"; +import deleteImage from "../images/delete.png"; + +function TodoItem({ id, done, text }) { + return ( +
+
+ {done && done} +
+
{text}
+
+ Delete +
+
+ ); +} + +export default TodoItem; diff --git a/src/components/TodoList.jsx b/src/components/TodoList.jsx new file mode 100644 index 00000000..fbed9b2f --- /dev/null +++ b/src/components/TodoList.jsx @@ -0,0 +1,16 @@ +import React from "react"; +import "../styles/TodoList.css"; +import TodoItem from "./TodoItem"; + +function TodoList() { + return ( +
+ + + + +
+ ); +} + +export default TodoList; diff --git a/src/images/delete.png b/src/images/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..a564a544dd7803462bf7366164290f405d543dc0 GIT binary patch literal 17727 zcmeIaWmuG9^EXT?(h3ODlF}(%ih_bPEZr_4CEcm0bazU_QcE`o($Xwl(y)ZY(y-69 zdjH?!{q}r#KRoYq9QTJkcG&B@&YGF?ocYZRA*#yq1h|yAXlQ5zZ{NI9M?*u0prK)) z;oJj$kzkNr1isLn)#YEJl@C+z0Drs!>%6s4QbJ<~XdE>3uhwW-s3yRN68NB@VP>PF zVFKUisNb?N{^uz=BpdU8XpFxNJLZEA(a>bj-oARF>4Cn#_#mBh+IQvXyu^!}LMEFe z8vjxK=NMv~*HvH@GyF{orrFH*cD*4&N4-n7d#-!b*Kb>((721?+K?zjd8@AY(hzqf zm=7O^X^IA*oW(Np;2wV4$ zT1Te5fv|p(xz$0OwLN-0_Je>*h}yMM@pJk^^o$r0oUW&V2^`w@(uC|Nmu)(A14A7& z#5^GC7UeGA$G+PWe-Oi1RM=sS4>=6e`eTw2nVBi=e@C10b=4)cFrfuUwe&c)KmH2p z;W#fs=Ef7}@N4irvrC$wcd$fId}`qncWhh7IS%6wwDDYj2sPOKlDN3s<8;IN*g&iyTy5>MPJ@{ZMR zj)L8w%e+@^g%Zi~RY^HMa(OU(vgE-61IaZ@ad&&k=n>^{$Zy=+2kTP0>Ih zy6BhBxfctp2?FmhywWp>_HUk5IC&}gQ$}TJlu9W3Au~7rK_FEX*)#iL@=!535J_r&B?|Shd)6{7^ECL z6H;#qBQAYCUH9k@|2)E|eMG^b-B@|TjEP|o5br5dTwkWc$Ex}Rmy@_JH6Vj$|0boj z;Tx+jdR^(b@Q6X!i_#_T7tbxZc`;tf6vwcGd}7R$O$Gv9ezuOM1ZLlZq=*-)ZSrL8+MW`0BBO|V;#qT-ut1#$d{5CswO&?ozpJx9-F6(< z4m13gKp{yUeOV*X?lrvPe9i`vvdn5@3_!z(1Qd+=EvYF3Kuh7Nmii1!`O2fAV^KfM z))9?;*7*vceI94)T&DY8MWSKgh%m@NotV@35+2O?@+WQK#$B89^%jk z1TX?DlYjI&8AXo(bXK*>@L`2r=Hc_;GSYO>(x})O9|+ zOkprK$5+Q0F1XsU)i2ZKZS^*+rhIYv^@m#!{U^H-YKB#9lAKZ8y60^L@v{zQx9Nnd zg$!j`loK--;iMIrdan)Q%n(!g9GhR+{hD!u(wGA{@=wfxo@q%7^oAbPgaJFB&Nj-- zLzCG1GJ4ztO8W8q0;W%%%pFAs_=IxhV``uOhS$m?dth<*}%Wt-xUeHGK}C^@JE)&zCD*3dwG;7e%R7bu9?bw z{c@RudB<(%*T!4-Z#yWV!O3I!Q?LJvp8j zlfu4S)&1-gT0mL?WHzxB9*qs_q`AIeyXkd>x7AmtJ_MEN)GoMcn|Iyaa$w|w21Zol z$nGoRpkt!sDnm1|ry6X4 zaN-3prvL6wAMNSyc2vUlHTp(fw4J8@>QW6>V>vOd5sc(;ncIBQ67cb( zEw};Bv#i&^i^q(rJg%m7)F+aKs?&dVpKGglnQjedw07+;RfZ)fTbgxmvNwQI;FUpWERyiD^E}xA5 zchlOiDf8_YDB#(i$9wQhFSo(R-mc+KiO9$x`HD$K4=HciQm(EyOnIVyq8LdZ(4mSg zH$dBnJ@?bx@?FN&%-R0@S0AaV=rCAkT^*koKV9s=MHW-Zm+x{t9zb*8ol}x$R{0gr z#YBWIuS8WOt392e%ifm0VtHm@qJnRc2%lHwJLeBm9(^syN{ACCM)Cd&y($ltlyldT zNUC>N`q!^cqutSwEAYMDCJpY~Bl$-iGf%O8Jp0#ux{66@8OO$zQybsL?TNiEm%Uvp zpXv{C@It?AGHvePDbVw3qKj_7RB5*8IhA*_pRe08pcB)Ej^ib9H5X)`T5cS_b%+kZ zx8~S0h&cKyOlTOGSlkJQK_nF^d~1d3mFopjpNK5EKwRz%j%uxAPBOuF1eedW3n&(% zwEv1L_d6M(&!?|MnRjP?!nbVaYCTV~-5F_JY^*m15?+{BH0lx-UATq>VzP5{KJ=jk zSS7QvfH5QoS+}Mcl;*R9|H}~iofTi~#JKc*TNSX4F zj`+&r}-Yhwfdw)Dm!29LHu`{G~v3YwK-I8APD2)Qb@zg{xK7Z?gM$J3rygT$#g1JKR+`Kw*y;{SpkG zoY&uv{JH#Zv-4Q!U5gB&uAY17L2+?+m5V=UT(yp90E+>*rcPGr+BcPZ7m>*cI-8>7 z@2nWG`zDW|3*7q8%k1>Pb4LB7t2s&C(p|5$v<;k&+2fx6=_|Qa|Nrzs8ZGwTg04cb zSD%Z#ATcpfjw~&0J)c7Z|4YH&L5M}tIuh!*6X0>-YTTfRTzQr8z&5SB%_;>;^EFpg zCxL?4ly-(yh<+hGZcx+oyLhE?n~CtCy8pahAJBN_;TvnloTh_KQUuw+TpPK4x`a|v zVi|g^z@s{;SuwJ3YEh?nTcg=!$h}r&lM>T03Y6@lVH9G$)Xy4lEup~5HOt@1@QSkh zx3u@N9nXAa9lnoJlX|(vE#SVl5b9*W{kNp62UY@Qqf~;}CB*YxutrNQX{t=r^@;QT zwMQ!{o}LWcjJ-qmFwD=glbu$gyq@~Z!Si^u+D z#Rjqvqx?@3Eg33-ZhPJTkr{B{y-=;h30d2}kHP4nWC9p}^?eh#3sY1cqW_(NYH9NQ zzuUskLu{4bEI`Nn?{^Ol6S$^H{Os>CG#b?HPTbcLP^O_?IvMjzULoLbmrJ-aVql*7 zQ$+{tZIS=R!#cJfAAU@v=|E{Cn~ho=6&q zv}bUBT=$2y9<2<=QjlWH{VFnnvA=5V!Sb==uP$8qR_V-=za(3%(Da0t9Qxk<-EbLt zF#5^*k(W!!>_n)RynOEq^HrYyc_%fzd;g?Lojh8@e~o9>YqEV~A~eA__j-G*Rw3>F zb<|Ji|Fn1*eWg(@i%BV-t24{UlM{QD7k<7Q;CP9$xd1g`!ZxZ!07g{D9YKa#>0a7* zcDvZyfaUl?HDrt@%60=TpqCgiW#V;r_(HcIE6LsWX2t}3cf)TLAn=V_j{8(!r~m0x zQBDV=)2Hr{3jJxQO{Fzq6PTGXHHMMOkEPwoS243%{3EZZkt|9iiXsC*-m5zPi&Hcy zE7|ui2%5lP{pA)pCERu#l<9l345eN+*!nGIC!~7Sh5Qji%@_@%>mje+;xg5C)ZL$hW)*Qw-<6tS z-O|0j5&K0im#fJX>A0?0{q?!PB*Jtw|G(A=J+B1%i3{<4x|vD~guvGIjb~UwM#tH{ z{<%^b-`Z<7knlhjd6q*?OVr;@>F~s=>wn?n-&Agnz}$LLadS3HSShkrJrogP6QPED zy)@(3lh%TgP~f&4#jcz8GJ_AOO7rJ&aftJIcXTI^^h%RVO(U%G_n+<$9Y<$XQT*FR zidY#=^Hx&GMOb&P{2h3IuD1KBuYw#U2XkOe$QxM;Cumq{;ZoAxsNG+alzaN;%U7@m#q#gNtK@p3{%0QIVZ0~$-=g!Uq zmZ&=My4XQ(P2%+q^DNqpGwkyg+I{9#ErNU2vpfHek#$uWh|v!09t|XFxw-DP?f2Qo zzWX}(QvvCAH*0UwqEdB`?w-hXrK)>WN&iHlg=D)1@nh2ISN7=pm zUO((HR};IH)kTevS4@k?Y`?Ha(BGAZbx7q7eQD6SsRpovy>d_??{!RXv z%VZi^N2uAHq{Rb*5k~L)J!a@-pk}mxrLnICt(*OXjX~zGei8C%Z(29*l5Ty2asrz2 z1v}gzOlxG|V?fB)O<(9Z`^C%BHDe}jB}|kU@M2?-{1O`QF;Au&>F#ae0kMP9HXhMO zZ8D^}V4!0;u~oY4><1p-$Wx6pXANGaDx-#OB+1s<;Ldl!0W_g63mDs9G+!R2l?Q-t z)2PTsgF20lS!JLD#>zVn0f~qf2mH7Lb%n1e^}cxkKp{yQUY~&-TUQP+OK6TCe+tZ; z-XCy-Z#Lp-|2xG0A2urZ#x;aCL&*eXC3;^g{st%Q6XrY<<2pC*2@lzD9&?>G)Q&yc zbN=%E!8TwHRTdYsagySiLUks6>1?d5c=OfSc6WC}g#a7AA6{@Mc_&>TkfH5=IcPlR zDJbExJ!)-S(#6ZUKku%!FemoZ%t*4{Jab9XE;ykuax7^L<75eW*A!;#cNzN9;jo*? z!OLtHOfqQz#$EeV`O()um$A3${6ks2bj!|>d{Rx_L3piStw)3DVNV1^>^iFVWDP?x zk+V?{CrFW@tU`!AnXAIckl(^hb(uG3r0D%5AKBDx&iBTH*?KPHyRgw@%QX={*Tp8+ ziqnWLWFeNG-drk`9C-y!c;lqs)$DN>`+M&}ImDyLl8RNio+~V~z(@JOH{TCtslGt(xCQd(BEwOiIOI=k-(1E$wwR z>+fREU+6maHC=p|rSw)Y32JxPWA{7b;s6;e`D4*#B3&j5jJbYZ*;G;9#-F;Ucu@0b zcJ1FBjqp@YR8Q1S&>iF%+%BxvxBL36K@ZxiPZBcP2TpW1f=m3*_kHd-+}emVZ#H_= z%%$EZeZ6D+vtSp9ryJ9_c;fTALSIjxCo$OQv5#-_-T{^F#zDW28B2fYiZ24%v~O2d zc1Q)_2p&uBrn3ndY?I6R5tkfnoNo1+&)XLs6gIu88(m_L%Rtsm%}WcFK=1rRtyL17 zlZyLi4U6Rgd}6XSzXBpN62Iul>h>MP^-C^gJR-LG2|MSnq>a@ss`>fzK^xh{d*yoc z?~0l*U)*eH4=E{B#PJjy#u8~Yt0JPh{4_Ecn{C^?*L98ztN7^_ zkwesy(~3!LzOkiyZ44Z(?QwpFoKbm+Wa5iq`5En^UZvL#gZoA^kL4^TDnFXeCwIv= zFWYU=vC&i{$=Bj(887dX2U;{s%xrXW)47T6c*h|ZN#A@xchTsA7HtisX;1Syt#g%R zOS9tL89Z3#&a=kX9(er2vX*e!#^3!-?hn%WQN_ds$B6MUh2J*>*3*6(D&`cXHEn}+ z`u5VT1_fin;P#o%1l{M@fp{%J zgK~CPdo=bj!MH`Tdb97)JHZ!!?kgD@)(@6vT(yxKB9UC~OQOS{kL1IJ?8cMgzJ4#9 zM!4x5Y6im$?H}2Geard`SP8Lk@!NUXVnyf`NiNLH zIu{hY`|AAkmnxYQfWTa5EO#?(#V>Ngey<%X-E>BtHIM$Jb3j%+<~9_&e#xo@ADO@G z9Hvuux11759OdS5YlIG}M3{fSG{uRoG0lcuF-rSg9O=LRQT?^R^0&Ns8OBM0B5TXd zS8n7t-(DJbgS^!ho^C;oeR#St^eg+xZ?;UHv!O3SF zn}_Mi!sc>f~8HKKufWNE49{)->jqN)3a1i5mv%UJ2up{--y8>Llg{A4Xc!X?=U z87ZN~K_&wypZMCDPvqU|n!t?@z?Y7fiZa-2eXt@@j^1(Wpr*%VFRzCxdzz8TpQ@Kr z3$bJFA`%mu$Hlx3YS6gXqc#SURN{H=%J?JH$oVs{q&S)xhr}a$lR73z((^Ki_HO8v z3=&KPx>8)MlIWVL3AVa?3futGV{TS^p^91y#w6X=u2qM|qIvUsU3!$M+57Qi)SR^F zWkJdOOX{x}p)q(qV9>tP!E4oynZ9|yT63dD?#~TZ%u+=jCZ_v0G|wCHCjIz_I9JK@cB@^2NNc4^b`8wT z!HOn#Rp7yNU8qp^5v)oQtWq?*TSYu`G2ob~C?$KCaKdvE_*t{f$?MBYINiXzM(*FX zk@$NmvHM%PhBDPQxMAqOhVMHi{FuS9CPoj1(LbB@DYmZh>1q>8gJy&(a8F3R zQNP0biOS7{{EZE znVDzqhZ%y~X-~YzdaT!mbaX5~oAW%jVVK2?&Uc0ke>=Xwb0YZ_7S4C3jDb&xiZi^4 zB~WWC8yGOQ^aF#=<@l`wK>QZ^$zo7UUjjJWq9pkj z2wMQcT#a!Y3@Es;g$xL*rFn^=ppphgAk4+8{VEioJve|cmk{DF-t|!)2yH2se<QJ}{EW&wo^`@6g2xIl__(AE>%#8BOBb2Hj0OvCQ5jIOh{NbDM-YJZ(c3) zn{r~|vD3z@O02g~Ckxu5u)OzVG&sWQax`%w0?2(aDfMUUxr;M;2_l0>7C!fMYCk0W zD%_Om>5_PuX_&d^)V&e}m?FWPZ^QF>6U*4wI)$gSwTQ)`Hu>e{)$>?ap5zwjfHN^2 ztivpK4c>tL>ZR-*VTXB(oH#x*K_&6@g^!Yaxerc)C6<1LB+NbT3BJ{hn&`1~*ZM%R zpIE5NQ+~fTG|Sa=y2KSG=JR^m0x5`#g z{YiTCzM$Q3u&v$LZ5ra6(j!5Z9^+vgkExw0icn|C+6OV$YBLPplxsoAzl@>Jwl)dG z#TEwbPU%VeB5%*D!L9>L6C*&xQ+dSt#}l&Rq2mZwxOIgEJc_X=IV*~TH2t!U68nd< z)5^d|FdrmXW|hDF8LSc7JU$#rKtNE@!|tbZKH7=F*AYF?xf2A+VYAGNW7d($i1lejvO(8zCtw%d&8G zyXj47-XG@2jdlrsLitCG&D66SZ24za1-O7O!cJfCJml=`OdCA7fo{zcCa<3mKBhuL zJ!|5wCH5RE#!to#+rqh<-7#U!SwWMH4XXiveVMRaA#SQHn*xY-g;Wm1 ztzC+uai7kfdg0{bW@<1ecc*9+TKBGmjIQ_feVeHkCdGN^*ZMmpa&0fDL1u*Vjus)LfQI3=JfjT2d#EIJkIdYXP7H^x_HM zqG^NxZ=Zu!!6LWxBgMM2ckj_y;ZIddt1`b=cTdk>Cmj=v-F-8Jn`Z5SE~^jyk@l>^ zWn$!0Tqm2p^0-s=@6+`h`s3d#BB+Eiox9}7k&B4&2X?W=s8v0;Osyat+3PksS#w!6V)lI0v)iVtYyduEiLtz zT`5uM(FuQOE3WKZSBy?dg4cx06NpWH{4lX-2p-fJ{j|JI4gq9=aSnrCr^c_p3nHN2b zXm|F$^7zX}wyS?z8?kG+K1e-WDz?DgA1J-V)h;L3HfTS~ zL_TfCI*eTwrByQBxC*Dvx!W>KGB^&2j3jI{GQGR!ZPM}O?2LYnn~(-yQ3hKEm#jn};M0eqA~{F0PURC@ z`6jc9{0PlIN8iKe%nNM_9p<6?1RJv4QRZ7z;>elHzG0Q|Bqrq_Gj>Use}@M1m`MYp zs$0~2?91<5pj)3`6ObebmQFmF>1|htDuFU=$M~{I$KBM%#U;fJ#eKtjDFjY+b)^%gHJ;$^?0u&oJEaz7kha$LEV@zvqN!XGbBnk3ji}$Lz$uAm`>AEC1WZ9=bhA(ZvEIGn&#U+1lc* z(eILO+V-y}`u_B}Wz2b&Ud$gST*03Zp1ilJGH9{<(b9-i-(Q>sBCSHJ^<3?@%Cp8d zi*aL?7a8Zpy;vR3$S0&oy z5AZyIdcB5w#PR>YEXnpKb)P=udTcD3UWna3vib6ke7aydv>WO))MkT8#zQy);=VHV1JQlX=eRXAiA)f3FiJ|oft$pHxG3hIb3|u&Ala_`+)q83 z9Gd+tx;qz2Jy<8M+1zB};#rxg+8Yugv+Rr9#^2~-8S&{JyxaL*zPXviLk4f*?#(dl zUMBhEU*uabOc$tjwSQjTxOH$6r8`UE7QBHlaS@S4d+GVg^OFd4Wq{^Og702@FY*As z##PnXT2y_q+n{P?JL=_qsb}x&aEuhiRwkv?x7}m*K1lj1xvbPL+`sZY>vqoxHZN`j zgY7qhhtrcFxBKIDalOBPk~1_XSks+N(HQT*w?fG{*&zRy-G$hR<_rIO2d+ zdI_q!cM#EUps|KDk{CARn+2utfd|RjE^cmK!c^%xEBgw8-xV-eapNT4}!ggfeQpzho?(O-S@)8+hifg5% zkio;jM!{;l;Go4SGgJ_rpH~`?*BZ}y!o!;3YbcjKIl;~iS~1x znzjO+XM);>i4Rct3ye5=Fs1K(c}Y)RZ0466RSs{M3&Z_-CiPMmiaDEreI?2Qg$ajI z$uU>0)W>nCG|dwBk7l>;iIyBqXS~gBjS)H|Y#^wtJ_w}gXYB0^1Ee4QaEk3^D;2OrR-V{Ip_~ALSXA`dzl+;XK0s(GZJz>E3I` zh*0DB01{DlCiHIwquavFyoM~Oq-cEom7iX0CxvJk+a~qtrL8>0VfTQ%Slg93tTXzs zSL}Nal0V!DzZ`CAgJn+Y4u$Y@0nm_11BRO~ll&A{{K$MRx*-MOAesE5`P{^X0o~rS z&<7iFj5Mm;SbB>WqXkM8?)0FSKt2``mU3y7g@U%BDA6giXoH!&dhy#*9hmiPj^qo@ z;trDJ1E$6s9Xx&Q2Yvi+flQq@D;HkRtYV1zz4{}5lppSUNf%p@aDejFcfgJDF|A>? zFdnij;vSvGQMetdRwHZlG=&q`S6(LcX4)z^A*;ZphBkls z)#;#gm36Hm%ibuB*icX`E=SwGEbJ&5V2KCUM<2=ek3~MK#)}K@DeSJ`!lP#r6EYfX z)g_scT5IVfRn_b!wXWA{)4s&5W*AIJYlTOZu$qjJppfafFwa{tq|3J7&GL^A3`IS3W5N7BsYkO7| zvLrq00j?@baK_=U1kT9nsL}9YW7l2<(JoMV7R?%r$cWnmX#S~1ANXYhL z@AP^96K1_q+Zm_c75_M-foNZj$`uU@{(gq>6BHmkiA9-~wskMiC{ynf%=(!WG_zuO za+p8iXP8#$>ivAX*_SRKDA<?4aN9QsjKlW74rU-M~k--^cL z_R?jd{pIFq+N|j9=!=xGG+~Fxf_GVbva!6vW0{)%t4@;KlHhYi9{agQJAE_OCM{{( z0sse(e6U@hmTRAg7_wxt@AZSQD^_^@k*8`;tMOdb2i0LZ1wvfkx-+Hhr0vXYFMAGV zxErPaI!$2*GV{3qB$9D(3qbv{ZuIyU)xxePzKJK8X{pCZE)PI+F$QlCPEY%%n$&NG zQS~#{OrM1SxRVaO*{E3Hig5O%=9Sm}>chTfMjGjKxgK>k5Td7rJ!y3&S?=p2EAt?O zv%6eLM_!eJp+@ZoXaaAsd`K(XHC#Cma?O4*cPbypI?AW_uOuU8G}u7$QM8gd;dSz1 zZ|u{l3$S}`5EWd;2kZD7c_J?uqn!iquV48G>mU=qVyH{v| zdDy7DemsK3tV%e6HGDj8UeV*KqTkchW@{v?o%Oeya+=Ss^d8p-yH+v5EAL0$=@Sf& zr%@t8$a-#Ge=8E!uQ^R_KaAvI52(OaF^SdTYdADJ__{*TuL%n>C;)8yLZ_4(@bpCd?sn6X$F~YvHcob;+ z8+v*2!ZKN4$!e}nPkT24Bildjka;hUjgN00L>0V!!eGeY13;4hAH9RDnC{*!&e|@%J zo{5%$Milp|gDwy}m>5w8i2||H_`LDD_3~WLSDp2iyd6QnK}ct=D&06Uu(%kw=X7hG zN+!5cC&gWC4U2czvsxr9d&{*pH(H#IYe};v%XO48eK>LOB4RbYm$a1JG7paIUCm=EcqmczBdO<$yO6=6Ba`fOe*_&CuQNpRR|o*{ zzbWiJQ4JuRB77RZO4R3cbH9oip&T+xEAxBRx9H1o8H~i~{$jh)^w`nDsI=xSpUvG` z)?&OpHQ#R3x=+4z!a+p2AGv_=YyI@5bw^c;3ndobW&ZBYPm+@NiN3x571EtDNRIBw zZW0#flY+ks?~R-w$e(v9UFJyA)2ILXb9S(FcG35_v425yY8Q)8){d0hdYHAL;jOLj z0M;1|s-D5!;nYs_)H{S#prgZQFRl~eo4ZDL??vU?B!&AqR_ihJ+Y(Loi%qmoQpzd< z&2A!OT(M7MnH6`}8a&@q(9(c$gB=~IN0OGU{j|8-ZXa9kR_zLH{hSQPhf~5k&wUQP zmm!zT$NXxgwsVO!b$6)?eQ#wOvilwx5ZRlD|v3 z@#W-95W@?`z}_Uf2cb_<2Lxu@vVB#Xke$B&a?f)Q z>T%{;of%~&@Ny}QHR_$+B|&&nJIcyTe=uW{>emS6zUU!pzqM<$l6Cv?j*Mdv$V^B) zC>F5Xi;LU0=+BBa|iWlw&lu#vRHYpJbKVQ{SlH;zl<*VX*W zJp4D)bnij@dUogtHRaevJJN1n&)eQ|^UJ%(9FWt_&7pjo^30ofLR{zdJPGe&2Eyh3 zg*{mrU_O}WqUYMKKU=${Z`HiL3;YUq9nxmaz@KWgEwUthcNqg0CRObl`P7VZOb{b~ zbC?71NWSH(OKPeg`8OOcd7m538=vQ5LxO)(uP0C3TJ^T~7nvTXwEO56 zxMQ9Ty>sG-vAUXMYko&O)qkjcb_3~YJHMbqZBX`0^fJP?u2;SE+`byzi5auY#aHJ8 zA!cCAy7RUsx6N?YoHr3ML9THv@t0+tccT)h+3-Kj)~X1Z)P~C<8Y3ek8B@MlnvoAC)0m&FXHzv`;I%85&QWmQR`h-m0+J78a?eSu&`IzqhOUQ)uQC)|6TJ*Yb0#E|XKarCu6eI{c- zKm|sx8F*^S265mD(LQvi`Eh9mCaDA}pqJRD4bNp8$6tS%vM9KTgspp-eM2#VqAfs_ ze){^_n7L7`yLErRu_48dJ2XLQdzecgn?(wPs7OgwF zXk@1ZdH1e+ub{9L)3oN$qG(a0Q3#K%oo@!U-4WQ_CG1x}qi;@t-exp18P@0 zNWP#uba3#ON|KCM-uNKA(!nHIZ8!h@$wVQt&&p1PGLtjP!gIYzMiB`V4s;NqbC(%p zp`l@Ap#B$tH^mjLZtksy)vw+I!|EQ|)Xe#()7=9WN|B@z{2ROdY3q?)Ld9pJXB_J< zepHD71x70+GMs_ZPuo>|jSl`?FK-O&q_jDjJ&$%aF6E3}aBQ$SAaM56-QD;6xxK>g zX$^Y*CmH2+sZybz_+yax+pd2rxYn*PTGUOW7`KBpbA{KJ>+n7O26Gt5=ayohbh3Ma z^0zvk1SWywb{$?e62azbZO+9=T*)vH+g0+w&m-2U}_U9_tQWx=NzfN)oF znE0nvv7XsaI{qoHwP`hKbJi~_t&?9Q`NF9{~9yGpI&nMjA~z0+d=ps zTlU}uf~N8PcsooiS+D+ZKT*s7f@Z#MKhx(n{cC5@X}m!JQ#4J`blZ*yRp!))PWk66nSvO$yjDnr+>5S!NSn;#c@)zhV^WqoX*26=C@A$1y_u{p@Wz- z$V{~#1pIR%o`2G&bXz>00M(JqCL>8=^zCmYpQNn-K(%0Lj3RS?_cMxnK&HyQQ2dK) zAidJl(bu8kCXuW>x_)!8b&!RCB3Sw_K!LNpwJw_$9|}63gt_`451O4_f6tl*q@OU7 zLY$A&y_}C$yVo>zkdW_FitqJrBaR~_i9anC6@Ejxzgy&$`bzU)?PW|B(0Q7=hQbOS0wq`iMcS~fuagbIBbi^2RCW>u$Qg&87u zX|t#B(71NDl3v6+?XrgC4V1E=p_QQDrh8SVadwSBz2P8M)IR2yoB0<}Q7K^DOVa2x zx*i(#@ntsHP9gUPE0N^hdH1{+u~4mq_#`fUAtCkOX6U|OZCB?p`E7q!5fKJf#PY?x zpkKpqBVT^%NgeH+>sMk1K=wHZ8XB7W0<`rcztu_~y_x6)50UxJU&2;u^&`W5@?z(%?;X$$Cn@igivjh_(u(s(8 z45%4@OIGkiE45gQmuvI`Q0<(~B5)yS-Ng4}Ger;sM^n4wu5FUdSi-%ZeALhhcT)fw zT5qK_qpq6257>s@U~*&4MV1sjpvr`7NgRGIvGE@#X# z&5{0|waisQ`;OyH)h_r4v;rzV*2xQ$N(H`Yd)AhRIpH1_5zF_3#7+HJf5O=*?7~;Q zC=+L`iJO^>EtJwbXY4l=s^IF_dGMzLa#V~Y@^ScBsWDB-iTdv)Z(l3FDt~Db^uGYj CNxm`w literal 0 HcmV?d00001 diff --git a/src/images/done.png b/src/images/done.png new file mode 100644 index 0000000000000000000000000000000000000000..bdd617282c3a7a7bbde5a46ff7373e9e956a4a25 GIT binary patch literal 6723 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 literal 0 HcmV?d00001 diff --git a/src/styles/TodoItem.css b/src/styles/TodoItem.css new file mode 100644 index 00000000..97020d7b --- /dev/null +++ b/src/styles/TodoItem.css @@ -0,0 +1,57 @@ +.remove { + display: flex; + align-items: center; + justify-content: center; + color: #dee2e6; + font-size: 24px; + cursor: pointer; + display: none; +} + +.remove:hover { + color: #ff6b6b; +} + +.todo-item-block { + display: flex; + align-items: center; + padding-top: 12px; + padding-bottom: 12px; +} + +.todo-item-block:hover .remove { + display: initial; +} + +.check-circle { + width: 32px; + height: 32px; + border-radius: 16px; + border: 1px solid #ced4da; + font-size: 24px; + display: flex; + align-items: center; + justify-content: center; + margin-right: 20px; + cursor: pointer; +} + +.check-circle.done { + border: 1px solid #38d9a9; + color: #38d9a9; +} + +.text { + flex: 1; + font-size: 21px; + color: #495057; +} + +.text.done { + color: #ced4da; +} + +img { + width: 24px; + height: 24px; +} diff --git a/src/styles/TodoList.css b/src/styles/TodoList.css new file mode 100644 index 00000000..455f4a16 --- /dev/null +++ b/src/styles/TodoList.css @@ -0,0 +1,6 @@ +.todo-list { + flex: 1; + padding: 20px 32px; + padding-bottom: 48px; + overflow-y: auto; +} From 7242301cb6603fa1df5d01388bf16649c85d2055 Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 22:22:33 +0900 Subject: [PATCH 07/12] =?UTF-8?q?Feat:=20Todo=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 4 +- src/components/TodoCreate.jsx | 32 +++++++++++++++ src/images/add.png | Bin 0 -> 6892 bytes src/styles/TodoCreate.css | 75 ++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 src/components/TodoCreate.jsx create mode 100644 src/images/add.png create mode 100644 src/styles/TodoCreate.css diff --git a/src/App.jsx b/src/App.jsx index 6b4e430b..2e6df1e5 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,8 +1,9 @@ import React from "react"; +import "./App.css"; import TodoBox from "./components/TodoBox"; import TodoHead from "./components/TodoHead"; import TodoList from "./components/TodoList"; -import "./App.css"; +import TodoCreate from "./components/TodoCreate"; function App() { return ( @@ -10,6 +11,7 @@ function App() { + ); diff --git a/src/components/TodoCreate.jsx b/src/components/TodoCreate.jsx new file mode 100644 index 00000000..ce6423e6 --- /dev/null +++ b/src/components/TodoCreate.jsx @@ -0,0 +1,32 @@ +import React, { useState } from "react"; +import "../styles/TodoCreate.css"; +import addImage from "../images/add.png"; + +function TodoCreate() { + const [open, setOpen] = useState(false); + const onToggle = () => setOpen(!open); + + return ( + <> + {open && ( +
+
+ +
+
+ )} + + + ); +} + +export default TodoCreate; diff --git a/src/images/add.png b/src/images/add.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce7c053ff7a1f7f0a53a4f2b3c1594f06549258 GIT binary patch literal 6892 zcmeHM{Z|ub7Jg@#Kuka*iWZJNnXXVQtjaF3AS)$M{J<7MRVWf5h^5%2MJh%>gd|Xx zdi+8WuplKKQAC7bX;2W8(Y9jC0#%gQf-n?mN<%&{CIphe&LsA88_O{L8pt*O&1aT9Q79aUu zR21+bY$||C-UkTTg}6M33jhZZ1RRJKBA0POvu5TQ@qJMQ==~uoj@#rhJ1uV}~MGu{| zru|22o>YAw>Mxtt8lLMKXHza+H=XP66RLC4Qw;5jM1;yfSpopTcEb+BpVSjJ6l1!+ zEN+e$3;%**kZJZd=?uZ*X5F{JrrFe*zJWY`&7y&s%$Jwjq9BWo4Dak4)$t6~rmbW#o8?%+E{F^OyqTj;x0h)ScqQP-~-E~!$+GC9^pzsJJ zIU&1H(%av8KUDqt&AZLxzYbyH!CZsPhdP{b0&6-D z)-N_rcl7gQUGsHasvn3AW*!lQI{#ep_XquG7B@w9#CxsSJu*qMz?o)ThM{e7*7PCT z$O3!5|9HJMr(hxh@cX36%?j$C#SD<}uU!kRsQ9fyfpcnx?GOnFBB+QuTWp2cnMMW0 zj}sP?jwoCPL87!JKiQnJ7>4c3*g>;AK`O40`M=uXWlPY3=iqDaw@|8bO>Ve`p= z*yF?@IVrL>wLD%PMu>&5(&_Hbf)Ca|BE<+^B#=L*zZ7VR0XG`(FHiFIqwIoBBrZ<0 z+~XmP?I4JeU4C%<@xCjh_P{8R_}X&6%-QoGYkSy9Z$gbgus5MvR^0qz?TOX(9;Bv8 zWN1C|p|ML$8VGbdWSpuEF*o#C7h@5loll zQ9EWqMI|AJh)oDDAZAo_!BZojaue(hn`U30wOsRxT}f&nuNE%HvJ`Wee>-;+OW11R z;{E#TwM{xl203R?1kP^!mbtK@?%p&krD#LGKF>6c2^Nj-I0l6N%d}lkNri?3+#g#M zar2oqV*l}2FA`gI;Ri?(( zrcmcYq@RxGU+f)q2KG%OXuLUxhAXNFT(Ton*@BZ#1T$IvEx zKjrk^2jBcq@0+;~_9jxxxu1VL7KPJ9=3hc_`|ux1~E3ml-V?s;b{gUg|2%Wzdq*P7*yKc$P47 z-|sO#3J!FEeqSt$AnI!hqP`Z0O#ZI8_7#$xs7qE1LZ*M1uDzHN|Clnovz0IHEt7h* zXj(Nyi4L!zZ{T;=*4A$pU=Biy#>7!}-s){sc7EO~mBuStdBa>qG4H^ZENk7#dI)ka lcEb*W%`5+Op0Eg+ql5B&htIBTYb5_PMQ)6aXbw*)`afV--p2p{ literal 0 HcmV?d00001 diff --git a/src/styles/TodoCreate.css b/src/styles/TodoCreate.css new file mode 100644 index 00000000..4d8b1d25 --- /dev/null +++ b/src/styles/TodoCreate.css @@ -0,0 +1,75 @@ +.circleButton { + background: #38d9a9; + z-index: 5; + cursor: pointer; + width: 80px; + height: 80px; + display: block; + align-items: center; + justify-content: center; + font-size: 60px; + position: absolute; + left: 50%; + bottom: 0px; + transform: translate(-50%, 50%); + color: white; + border-radius: 50%; + border: none; + outline: none; + display: flex; + align-items: center; + justify-content: center; + transition: 0.125s all ease-in; +} + +.circleButton:hover { + background: #63e6be; +} + +.circleButton:active { + background: #20c997; +} + +.circleButton.open { + background: #ff6b6b; +} + +.circleButton.open:hover { + background: #ff8787; +} + +.circleButton.open:active { + background: #fa5252; +} + +.circleButton.open { + transform: translate(-50%, 50%) rotate(45deg); +} + +.Input { + padding: 12px; + border-radius: 4px; + border: 1px solid rgb(254, 254, 254); + width: 100%; + outline: none; + font-size: 18px; + box-sizing: border-box; +} + +.InsertFormPositioner { + width: 100%; + bottom: 0; + left: 0; + position: absolute; +} + +.InsertForm { + background: #f8f9fa; + padding-left: 32px; + padding-top: 32px; + padding-right: 32px; + padding-bottom: 72px; + border-bottom-left-radius: 16px; + border-bottom-right-radius: 16px; + border-top: 1px solid #e9ecef; +} From 55fe933c74fc06551fde10bb7dc8c783cc00c455 Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 22:32:37 +0900 Subject: [PATCH 08/12] =?UTF-8?q?Feat:=20=EC=83=81=ED=83=9C=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20TodoContext=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.jsx | 5 ++- src/components/TodoContext.jsx | 70 ++++++++++++++++++++++++++++++++++ src/components/TodoHead.jsx | 3 ++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/components/TodoContext.jsx diff --git a/src/App.jsx b/src/App.jsx index 2e6df1e5..a149bb2c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -4,16 +4,17 @@ import TodoBox from "./components/TodoBox"; import TodoHead from "./components/TodoHead"; import TodoList from "./components/TodoList"; import TodoCreate from "./components/TodoCreate"; +import { TodoProvider } from "./components/TodoContext"; function App() { return ( - <> + - + ); } diff --git a/src/components/TodoContext.jsx b/src/components/TodoContext.jsx new file mode 100644 index 00000000..ea7560f2 --- /dev/null +++ b/src/components/TodoContext.jsx @@ -0,0 +1,70 @@ +import React, { useReducer, createContext, useContext, useRef } from "react"; + +const initialTodos = [ + { + id: 1, + text: "μ‹€μ‹œκ°„ μ‹œμŠ€ν…œ κ³Όμ œμ™„μ„±", + done: true, + }, + { + id: 2, + text: "μΊ‘μŠ€ν†€ λ””μžμΈ μ΅œμ’… λ³΄κ³ μ„œ μž‘μ„±", + done: true, + }, + { + id: 3, + text: "κ³΅μž‘λ°œ λ°œν‘œ 자료 μ™„μ„±", + done: false, + }, + { + id: 4, + text: "μΉ΄ν…ŒμΊ  λ‚΄μš© 볡슡", + done: false, + }, +]; + +function todoReducer(state, action) { + switch (action.type) { + case "CREATE": + return state.concat(action.todo); + case "TOGGLE": + return state.map((todo) => + todo.id === action.id ? { ...todo, done: !todo.done } : todo + ); + case "REMOVE": + return state.filter((todo) => todo.id !== action.id); + default: + throw new Error(`Unhandled action type: ${action.type}`); + } +} + +const TodoStateContext = createContext(); +const TodoDispatchContext = createContext(); +const TodoNextIdContext = createContext(); + +export function TodoProvider({ children }) { + const [state, dispatch] = useReducer(todoReducer, initialTodos); + const nextId = useRef(5); + + return ( + + + + {children} + + + + ); +} + +export function useTodoState() { + return useContext(TodoStateContext); +} + +export function useTodoDispatch() { + return useContext(TodoDispatchContext); +} + +export function useTodoNextId() { + return useContext(TodoNextIdContext); +} diff --git a/src/components/TodoHead.jsx b/src/components/TodoHead.jsx index 327a1386..c22b9e07 100644 --- a/src/components/TodoHead.jsx +++ b/src/components/TodoHead.jsx @@ -1,7 +1,10 @@ import React from "react"; import "../styles/TodoHead.css"; +import { useTodoState } from "./TodoContext"; function TodoHead() { + const todos = useTodoState(); + console.log(todos); return (

2024λ…„ 6μ›” 9일

From b38bab7c9a112e06136edfbf0b9fee58fbfb87bd Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 23:06:47 +0900 Subject: [PATCH 09/12] =?UTF-8?q?Refactor:=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EA=B0=80=EB=8F=85=EC=84=B1=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.css | 1 - src/App.jsx | 2 +- src/{components => }/TodoContext.jsx | 0 src/components/TodoCreate.jsx | 24 +++++++++++++++++++++++- src/components/TodoHead.jsx | 21 ++++++++++++++++----- src/components/TodoItem.jsx | 11 ++++++++--- src/components/TodoList.jsx | 14 ++++++++++---- 7 files changed, 58 insertions(+), 15 deletions(-) rename src/{components => }/TodoContext.jsx (100%) diff --git a/src/App.css b/src/App.css index dc38fea7..973947cd 100644 --- a/src/App.css +++ b/src/App.css @@ -1,4 +1,3 @@ -/* App.css */ body { background: #d3d3d3; } diff --git a/src/App.jsx b/src/App.jsx index a149bb2c..2d83c8ec 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -4,7 +4,7 @@ import TodoBox from "./components/TodoBox"; import TodoHead from "./components/TodoHead"; import TodoList from "./components/TodoList"; import TodoCreate from "./components/TodoCreate"; -import { TodoProvider } from "./components/TodoContext"; +import { TodoProvider } from "./TodoContext"; function App() { return ( diff --git a/src/components/TodoContext.jsx b/src/TodoContext.jsx similarity index 100% rename from src/components/TodoContext.jsx rename to src/TodoContext.jsx diff --git a/src/components/TodoCreate.jsx b/src/components/TodoCreate.jsx index ce6423e6..86f64769 100644 --- a/src/components/TodoCreate.jsx +++ b/src/components/TodoCreate.jsx @@ -1,20 +1,41 @@ import React, { useState } from "react"; import "../styles/TodoCreate.css"; import addImage from "../images/add.png"; +import { useTodoDispatch, useTodoNextId } from "../TodoContext"; function TodoCreate() { const [open, setOpen] = useState(false); + const [value, setValue] = useState(""); + const dispatch = useTodoDispatch(); + const nextId = useTodoNextId(); const onToggle = () => setOpen(!open); + const onChange = (e) => setValue(e.target.value); + const onSubmit = (e) => { + e.preventDefault(); + dispatch({ + type: "CREATE", + todo: { + id: nextId.current, + text: value, + done: false, + }, + }); + setValue(""); + setOpen(false); + nextId.current += 1; + }; return ( <> {open && (
-
+
@@ -22,6 +43,7 @@ function TodoCreate() { diff --git a/src/components/TodoHead.jsx b/src/components/TodoHead.jsx index c22b9e07..ed9df9a3 100644 --- a/src/components/TodoHead.jsx +++ b/src/components/TodoHead.jsx @@ -1,15 +1,26 @@ import React from "react"; import "../styles/TodoHead.css"; -import { useTodoState } from "./TodoContext"; +import { useTodoState } from "../TodoContext"; function TodoHead() { const todos = useTodoState(); - console.log(todos); + const undoneTasks = todos.filter((todo) => !todo.done); + + const today = new Date(); + const dateString = today.toLocaleDateString("ko-KR", { + year: "numeric", + month: "long", + day: "numeric", + }); + const dayName = today.toLocaleDateString("ko-KR", { weekday: "long" }); + return (
-

2024λ…„ 6μ›” 9일

-
μΌμš”μΌ
-
ν•  일 2개 λ‚¨μŒ
+

Todos

+
+ {dateString} {dayName} +
+
ν•  일 {undoneTasks.length}개 λ‚¨μŒ
); } diff --git a/src/components/TodoItem.jsx b/src/components/TodoItem.jsx index 06c72b99..ad2fbdf3 100644 --- a/src/components/TodoItem.jsx +++ b/src/components/TodoItem.jsx @@ -2,19 +2,24 @@ import React from "react"; import "../styles/TodoItem.css"; import doneImage from "../images/done.png"; import deleteImage from "../images/delete.png"; +import { useTodoDispatch } from "../TodoContext"; function TodoItem({ id, done, text }) { + const dispatch = useTodoDispatch(); + const onToggle = () => dispatch({ type: "TOGGLE", id }); + const onRemove = () => dispatch({ type: "REMOVE", id }); return (
-
+
{done && done}
{text}
-
+
Delete
); } -export default TodoItem; +export default React.memo(TodoItem); +// λ‹€λ₯Έ ν•­λͺ© μ—…λ°μ΄νŠΈ -> λΆˆν•„μš”ν•œ λ¦¬λ Œλ”λ§ λ°©μ§€λ‘œ μ„±λŠ₯ μ΅œμ ν™” diff --git a/src/components/TodoList.jsx b/src/components/TodoList.jsx index fbed9b2f..cf96d478 100644 --- a/src/components/TodoList.jsx +++ b/src/components/TodoList.jsx @@ -1,14 +1,20 @@ import React from "react"; import "../styles/TodoList.css"; import TodoItem from "./TodoItem"; +import { useTodoState } from "../TodoContext"; function TodoList() { + const todos = useTodoState(); return (
- - - - + {todos.map((todo) => ( + + ))}
); } From 79de5d07d653fa75c944017ab5a249753e805725 Mon Sep 17 00:00:00 2001 From: seongikx Date: Sun, 9 Jun 2024 23:24:53 +0900 Subject: [PATCH 10/12] =?UTF-8?q?Feat:=20=EA=B3=B5=EB=B0=B1=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=20=EB=B0=A9=EC=A7=80=20=EB=B0=8F=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TodoCreate.jsx | 31 +++++++++++++++++-------------- src/styles/TodoItem.css | 4 ---- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/components/TodoCreate.jsx b/src/components/TodoCreate.jsx index 86f64769..2703d810 100644 --- a/src/components/TodoCreate.jsx +++ b/src/components/TodoCreate.jsx @@ -12,24 +12,27 @@ function TodoCreate() { const onChange = (e) => setValue(e.target.value); const onSubmit = (e) => { e.preventDefault(); - dispatch({ - type: "CREATE", - todo: { - id: nextId.current, - text: value, - done: false, - }, - }); - setValue(""); - setOpen(false); - nextId.current += 1; + if (value.trim().length > 0) { + // 곡백 μž…λ ₯ λ°©μ§€ + dispatch({ + type: "CREATE", + todo: { + id: nextId.current, + text: value, + done: false, + }, + }); + setValue(""); + setOpen(false); + nextId.current += 1; + } }; return ( <> {open && (
-
+
-
+
)}
); } From be127702fcc6253c44281ef36ce07db3e43a5ed0 Mon Sep 17 00:00:00 2001 From: seongikx Date: Mon, 10 Jun 2024 00:05:31 +0900 Subject: [PATCH 12/12] =?UTF-8?q?Docs:=20=EA=B5=AC=ED=98=84=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=A0=90=EA=B2=80=20=EB=B0=8F=20=EA=B2=80=ED=86=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 5c155071..d71614da 100644 --- a/README.md +++ b/README.md @@ -10,27 +10,27 @@ ν•˜λ£¨ λ˜λŠ” ν•œ 주의 ν•  일 λͺ©λ‘μ„ μ—…λ°μ΄νŠΈν•˜λŠ” ν•  일 λͺ©λ‘μ„ κ΅¬ν˜„ν•œλ‹€. **React 라이브러리λ₯Ό μ‚¬μš©ν•˜μ—¬ μ›Ή μ•±μœΌλ‘œ κ΅¬ν˜„ν•œλ‹€.** -- [ ] ν•  일을 μΆ”κ°€ν•˜κ³  μ‚­μ œν•  수 μžˆλ‹€. -- [ ] ν•  일을 μΆ”κ°€ν•  λ•Œ μ‚¬μš©μžλŠ” Enter ν‚€λ‚˜ μΆ”κ°€ λ²„νŠΌμ„ μ‚¬μš©ν•˜μ—¬ ν•  일을 λͺ©λ‘μ— μΆ”κ°€ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€. -- [ ] μ‚¬μš©μžκ°€ 아무것도 μž…λ ₯ν•˜μ§€ μ•Šμ€ κ²½μš°μ—λŠ” ν•  일을 μΆ”κ°€ν•  수 μ—†λ‹€. -- [ ] ν•  일의 λͺ©λ‘μ„ λ³Ό 수 μžˆλ‹€. -- [ ] ν•  일의 μ™„λ£Œ μƒνƒœλ₯Ό μ „ν™˜ν•  수 μžˆλ‹€. +- [x] ν•  일을 μΆ”κ°€ν•˜κ³  μ‚­μ œν•  수 μžˆλ‹€. +- [x] ν•  일을 μΆ”κ°€ν•  λ•Œ μ‚¬μš©μžλŠ” Enter ν‚€λ‚˜ μΆ”κ°€ λ²„νŠΌμ„ μ‚¬μš©ν•˜μ—¬ ν•  일을 λͺ©λ‘μ— μΆ”κ°€ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€. +- [x] μ‚¬μš©μžκ°€ 아무것도 μž…λ ₯ν•˜μ§€ μ•Šμ€ κ²½μš°μ—λŠ” ν•  일을 μΆ”κ°€ν•  수 μ—†λ‹€. +- [x] ν•  일의 λͺ©λ‘μ„ λ³Ό 수 μžˆλ‹€. +- [x] ν•  일의 μ™„λ£Œ μƒνƒœλ₯Ό μ „ν™˜ν•  수 μžˆλ‹€. ## πŸš€ 선택 μš”κ΅¬ 사항 βœ… - [ ] ν˜„μž¬ μ§„ν–‰ 쀑인 ν•  일, μ™„λ£Œλœ ν•  일, λͺ¨λ“  ν•  일을 필터링할 수 μžˆλ‹€. -- [ ] ν•΄μ•Ό ν•  일의 총개수λ₯Ό 확인할 수 μžˆλ‹€. +- [x] ν•΄μ•Ό ν•  일의 총개수λ₯Ό 확인할 수 μžˆλ‹€. - [ ] μƒˆλ‘œκ³ μΉ¨μ„ ν•˜μ—¬λ„ 이전에 μž‘μ„±ν•œ λ°μ΄ν„°λŠ” μœ μ§€λ˜μ–΄μ•Ό ν•œλ‹€. ## 🎯 주의 ν•΄μ•Ό ν•  ν”„λ‘œκ·Έλž˜λ° μš”κ΅¬ 사항 βœ… -- [ ] ν”„λ‘œκ·Έλž¨ μ‹€ν–‰μ˜ μ‹œμž‘μ μ€ App.js 이닀. -- [ ] package.json νŒŒμΌμ€ λ³€κ²½ν•  수 μ—†μœΌλ©°, 제곡된 λΌμ΄λΈŒλŸ¬λ¦¬μ™€ μŠ€νƒ€μΌ 라이브러리 μ΄μ™Έμ˜ μ™ΈλΆ€ λΌμ΄λΈŒλŸ¬λ¦¬λŠ” μ‚¬μš©ν•˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€. -- [ ] ν”„λ‘œκ·Έλž¨ μ’…λ£Œ μ‹œ process.exit() λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•ŠλŠ”λ‹€. -- [ ] indent(인덴트, λ“€μ—¬μ“°κΈ°) depthλ₯Ό 3이 λ„˜μ§€ μ•Šλ„λ‘ κ΅¬ν˜„ν•œλ‹€. 2κΉŒμ§€λ§Œ ν—ˆμš©ν•œλ‹€. -- [ ] ν•¨μˆ˜(λ˜λŠ” λ©”μ„œλ“œ)의 길이가 15라인을 λ„˜μ–΄κ°€μ§€ μ•Šλ„λ‘ κ΅¬ν˜„ν•œλ‹€. +- [x] ν”„λ‘œκ·Έλž¨ μ‹€ν–‰μ˜ μ‹œμž‘μ μ€ App.js 이닀. +- [x] package.json νŒŒμΌμ€ λ³€κ²½ν•  수 μ—†μœΌλ©°, 제곡된 λΌμ΄λΈŒλŸ¬λ¦¬μ™€ μŠ€νƒ€μΌ 라이브러리 μ΄μ™Έμ˜ μ™ΈλΆ€ λΌμ΄λΈŒλŸ¬λ¦¬λŠ” μ‚¬μš©ν•˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€. +- [x] ν”„λ‘œκ·Έλž¨ μ’…λ£Œ μ‹œ process.exit() λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•ŠλŠ”λ‹€. +- [x] indent(인덴트, λ“€μ—¬μ“°κΈ°) depthλ₯Ό 3이 λ„˜μ§€ μ•Šλ„λ‘ κ΅¬ν˜„ν•œλ‹€. 2κΉŒμ§€λ§Œ ν—ˆμš©ν•œλ‹€. +- [x] ν•¨μˆ˜(λ˜λŠ” λ©”μ„œλ“œ)의 길이가 15라인을 λ„˜μ–΄κ°€μ§€ μ•Šλ„λ‘ κ΅¬ν˜„ν•œλ‹€. ### 과제 제좜 μ „ 체크리슀트 -- [ ] ν„°λ―Έλ„μ—μ„œ node --version 을 μ‹€ν–‰ν•˜μ—¬ Node.js 버전이 18.17.1 이상인지 ν™•μΈν•œλ‹€. -- [ ] npm install , npm run start λͺ…λ Ή μž…λ ₯ν•˜μ—¬ νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜ν•œ ν›„ μ‹€ν–‰ν•˜λŠ” 데 λ¬Έμ œκ°€ μ—†μ–΄μ•Ό ν•œλ‹€. +- [x] ν„°λ―Έλ„μ—μ„œ node --version 을 μ‹€ν–‰ν•˜μ—¬ Node.js 버전이 18.17.1 이상인지 ν™•μΈν•œλ‹€. +- [x] npm install , npm run start λͺ…λ Ή μž…λ ₯ν•˜μ—¬ νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜ν•œ ν›„ μ‹€ν–‰ν•˜λŠ” 데 λ¬Έμ œκ°€ μ—†μ–΄μ•Ό ν•œλ‹€.