diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..a3d35f6 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de328d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +week1/ +week2/ +week3/ \ No newline at end of file diff --git a/week1/TodoList/assets/icons/close.svg b/week1/TodoList/assets/icons/close.svg deleted file mode 100644 index ec91af4..0000000 --- a/week1/TodoList/assets/icons/close.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/week1/TodoList/index.html b/week1/TodoList/index.html deleted file mode 100644 index 9e9e1ac..0000000 --- a/week1/TodoList/index.html +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - Document - - -
-

Web To Do

-
- - -
-
-
-
-

Not Started

-
-
- -
-
- -
-
- -
-
- -
-
-
-
-

Done

-
-
- -
-
- -
-
- -
-
-
-
- - diff --git a/week1/TodoList/styles/button/style.css b/week1/TodoList/styles/button/style.css deleted file mode 100644 index 9df91bd..0000000 --- a/week1/TodoList/styles/button/style.css +++ /dev/null @@ -1,6 +0,0 @@ -.plus_button { - cursor: pointer; - border: none; - background-color: darkgray; - opacity: 0.7; -} diff --git a/week1/TodoList/styles/common/style.css b/week1/TodoList/styles/common/style.css deleted file mode 100644 index f82146a..0000000 --- a/week1/TodoList/styles/common/style.css +++ /dev/null @@ -1,15 +0,0 @@ -.p-1020 { - padding: 10px 20px; -} - -.pR-60 { - padding-right: 60px; -} - -.w-200 { - width: 200px; -} - -.r-10 { - border-radius: 10px; -} diff --git a/week1/TodoList/styles/ellipsis/style.css b/week1/TodoList/styles/ellipsis/style.css deleted file mode 100644 index 5453336..0000000 --- a/week1/TodoList/styles/ellipsis/style.css +++ /dev/null @@ -1,7 +0,0 @@ -.ellipsis { - text-overflow: ellipsis; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 1; - overflow: hidden; -} diff --git a/week1/TodoList/styles/font/style.css b/week1/TodoList/styles/font/style.css deleted file mode 100644 index d2611eb..0000000 --- a/week1/TodoList/styles/font/style.css +++ /dev/null @@ -1,14 +0,0 @@ -.large { - font-family: "Pretendard-Bold"; - font-size: 42px; -} - -.medium { - font-family: "Pretendard-Medium"; - font-size: 36px; -} - -.small { - font-family: "Pretendard-Regular"; - font-size: 21px; -} diff --git a/week1/TodoList/styles/input/style.css b/week1/TodoList/styles/input/style.css deleted file mode 100644 index 252a241..0000000 --- a/week1/TodoList/styles/input/style.css +++ /dev/null @@ -1,33 +0,0 @@ -.input_box { - position: relative; - animation: 3s linear infinite inputAni; -} - -.input_box img { - cursor: pointer; - position: absolute; - right: 10px; - top: 0; - bottom: 0; - margin: auto 0; -} - -.input { - border: none; - box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.3); -} - -@keyframes inputAni { - 0% { - transform: rotateY(0); - } - 33% { - transform: rotateY(30deg); - } - 66% { - transform: rotateY(-30deg); - } - 100% { - transform: rotateY(0deg); - } -} diff --git a/week1/TodoList/styles/main/style.css b/week1/TodoList/styles/main/style.css deleted file mode 100644 index 8cc4169..0000000 --- a/week1/TodoList/styles/main/style.css +++ /dev/null @@ -1,17 +0,0 @@ -.main { - display: flex; - gap: 180px; -} - -.main section { - display: flex; - flex-direction: column; - align-items: center; - gap: 14px; -} - -.main section div { - display: flex; - flex-direction: column; - gap: 10px; -} diff --git a/week1/TodoList/styles/style.css b/week1/TodoList/styles/style.css deleted file mode 100644 index 33d3136..0000000 --- a/week1/TodoList/styles/style.css +++ /dev/null @@ -1,180 +0,0 @@ -@import url("../styles/font/style.css"); -@import url("../styles/input/style.css"); -@import url("../styles/main/style.css"); -@import url("../styles/button/style.css"); -@import url("../styles/ellipsis/style.css"); -@import url("../styles/common/style.css"); - -@font-face { - font-family: "Pretendard-Regular"; - src: url("https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff") - format("woff"); - font-weight: 400; - font-style: normal; -} -@font-face { - font-family: "Pretendard-Medium"; - src: url("https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Medium.woff") - format("woff"); - font-weight: 500; - font-style: normal; -} -@font-face { - font-family: "Pretendard-Bold"; - src: url("https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Bold.woff") - format("woff"); - font-weight: 600; - font-style: normal; -} - -/* reset css */ -html, -body, -div, -span, -applet, -object, -iframe, -h1, -h2, -h3, -h4, -h5, -h6, -p, -blockquote, -pre, -a, -abbr, -acronym, -address, -big, -cite, -code, -del, -dfn, -em, -img, -ins, -kbd, -q, -s, -samp, -small, -strike, -strong, -sub, -sup, -tt, -var, -b, -u, -i, -center, -dl, -dt, -dd, -ol, -ul, -li, -fieldset, -form, -label, -legend, -table, -caption, -tbody, -tfoot, -thead, -tr, -th, -td, -article, -aside, -canvas, -details, -embed, -figure, -figcaption, -footer, -header, -hgroup, -menu, -nav, -output, -ruby, -section, -summary, -time, -mark, -audio, -video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -menu, -nav, -section { - display: block; -} -body { - line-height: 1; -} -ol, -ul { - list-style: none; -} -blockquote, -q { - quotes: none; -} -blockquote:before, -blockquote:after, -q:before, -q:after { - content: ""; - content: none; -} -table { - border-collapse: collapse; - border-spacing: 0; -} - -/* index.html css */ -body { - display: flex; - flex-direction: column; - align-items: center; - gap: 200px; - width: 100vw; - padding-top: 140px; - background: linear-gradient( - 270deg, - rgba(178, 204, 229, 1), - rgba(250, 182, 173, 1) - ); -} - -.main_section { - display: flex; - flex-direction: column; - align-items: center; - gap: 20px; -} - -.main_section div { - display: flex; - gap: 10px; -} diff --git "a/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img1.png" "b/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img1.png" deleted file mode 100644 index b6629b1..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img1.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img2.png" "b/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img2.png" deleted file mode 100644 index 8748839..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img2.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img3.png" "b/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img3.png" deleted file mode 100644 index 320549a..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img3.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img4.png" "b/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img4.png" deleted file mode 100644 index 18d26b1..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\203\201\354\235\230/img4.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img1.png" "b/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img1.png" deleted file mode 100644 index 8d8cdd7..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img1.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img2.png" "b/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img2.png" deleted file mode 100644 index 1fd4019..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img2.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img3.png" "b/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img3.png" deleted file mode 100644 index 1055bdb..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img3.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img4.png" "b/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img4.png" deleted file mode 100644 index 60ad82a..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\213\240\353\260\234/img4.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img1.png" "b/week1/shoppingList/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img1.png" deleted file mode 100644 index 080febc..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img1.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img2.png" "b/week1/shoppingList/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img2.png" deleted file mode 100644 index 5b1429e..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img2.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img3.png" "b/week1/shoppingList/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img3.png" deleted file mode 100644 index cfe166f..0000000 Binary files "a/week1/shoppingList/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img3.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\355\225\230\354\235\230/img1.png" "b/week1/shoppingList/assets/contents/\355\225\230\354\235\230/img1.png" deleted file mode 100644 index 6067525..0000000 Binary files "a/week1/shoppingList/assets/contents/\355\225\230\354\235\230/img1.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\355\225\230\354\235\230/img2.png" "b/week1/shoppingList/assets/contents/\355\225\230\354\235\230/img2.png" deleted file mode 100644 index 823a470..0000000 Binary files "a/week1/shoppingList/assets/contents/\355\225\230\354\235\230/img2.png" and /dev/null differ diff --git "a/week1/shoppingList/assets/contents/\355\225\230\354\235\230/img3.png" "b/week1/shoppingList/assets/contents/\355\225\230\354\235\230/img3.png" deleted file mode 100644 index 30de1f4..0000000 Binary files "a/week1/shoppingList/assets/contents/\355\225\230\354\235\230/img3.png" and /dev/null differ diff --git a/week1/shoppingList/assets/header/shop.svg b/week1/shoppingList/assets/header/shop.svg deleted file mode 100644 index f2f87a9..0000000 --- a/week1/shoppingList/assets/header/shop.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/week1/shoppingList/assets/icons/like.svg b/week1/shoppingList/assets/icons/like.svg deleted file mode 100644 index 85c0a55..0000000 --- a/week1/shoppingList/assets/icons/like.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/week1/shoppingList/index.html b/week1/shoppingList/index.html deleted file mode 100644 index ccc248b..0000000 --- a/week1/shoppingList/index.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - 주용이의 쇼핑몰 - - -
- -

주용이의 쇼핑몰

- -
-
-
- 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 - 배너 이미지 -
-
-
-
-

전체

-
-
- 카드 이미지 - 좋아요 이미지 -

화이트 자켓

-

23000원

-
-
- 카드 이미지 - 좋아요 이미지 -

맨투맨

-

18000원

-
-
- 카드 이미지 - 좋아요 이미지 -

바람막이

-

22000원

-
-
- 카드 이미지 - 좋아요 이미지 -

셔츠

-

20000원

-
-
- 카드 이미지 - 좋아요 이미지 -

핀턱 코튼 와이드 팬츠

-

50000원

-
-
- 카드 이미지 - 좋아요 이미지 -

크로스 트레이닝 팬츠

-

42000원

-
-
- 카드 이미지 - 좋아요 이미지 -

블랙 와이드 팬츠

-

39000원

-
-
- 카드 이미지 - 좋아요 이미지 -

더비 슈즈

-

72000원

-
-
- 카드 이미지 - 좋아요 이미지 -

패디드 슬리퍼

-

35000원

-
-
- 카드 이미지 - 좋아요 이미지 -

플립 플롭

-

22000원

-
-
- 카드 이미지 - 좋아요 이미지 -

어그 부츠

-

60000원

-
-
-
-
-

상의

-
-
- 카드 이미지 - 좋아요 이미지 -

화이트 자켓

-

23000원

-
-
- 카드 이미지 - 좋아요 이미지 -

맨투맨

-

18000원

-
-
- 카드 이미지 - 좋아요 이미지 -

바람막이

-

22000원

-
-
- 카드 이미지 - 좋아요 이미지 -

셔츠

-

20000원

-
-
-
-
-

하의

-
-
- 카드 이미지 - 좋아요 이미지 -

핀턱 코튼 와이드 팬츠

-

50000원

-
-
- 카드 이미지 - 좋아요 이미지 -

크로스 트레이닝 팬츠

-

42000원

-
-
- 카드 이미지 - 좋아요 이미지 -

블랙 와이드 팬츠

-

39000원

-
-
- -
-
-

신발

-
-
- 카드 이미지 - 좋아요 이미지 -

더비 슈즈

-

72000원

-
-
- 카드 이미지 - 좋아요 이미지 -

패디드 슬리퍼

-

35000원

-
-
- 카드 이미지 - 좋아요 이미지 -

플립 플롭

-

22000원

-
-
- 카드 이미지 - 좋아요 이미지 -

어그 부츠

-

60000원

-
-
-
-
- - - - diff --git a/week1/shoppingList/style.css b/week1/shoppingList/style.css deleted file mode 100644 index d141e97..0000000 --- a/week1/shoppingList/style.css +++ /dev/null @@ -1,172 +0,0 @@ -@import url("./styles/card/style.css"); -@import url("./styles/font/style.css"); -@import url("./styles/footer/style.css"); -@import url("./styles/header/style.css"); -@import url("./styles/main/style.css"); -@import url("./styles/nav/style.css"); -@import url("./styles/section/style.css"); -@import url("./styles/slider/style.css"); - -@font-face { - font-family: "Pretendard-Regular"; - src: url("https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff") - format("woff"); - font-weight: 400; - font-style: normal; -} -@font-face { - font-family: "Pretendard-Medium"; - src: url("https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Medium.woff") - format("woff"); - font-weight: 500; - font-style: normal; -} -@font-face { - font-family: "Pretendard-Bold"; - src: url("https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Bold.woff") - format("woff"); - font-weight: 600; - font-style: normal; -} - -/* reset css */ -html, -body, -div, -span, -applet, -object, -iframe, -h1, -h2, -h3, -h4, -h5, -h6, -p, -blockquote, -pre, -a, -abbr, -acronym, -address, -big, -cite, -code, -del, -dfn, -em, -img, -ins, -kbd, -q, -s, -samp, -small, -strike, -strong, -sub, -sup, -tt, -var, -b, -u, -i, -center, -dl, -dt, -dd, -ol, -ul, -li, -fieldset, -form, -label, -legend, -table, -caption, -tbody, -tfoot, -thead, -tr, -th, -td, -article, -aside, -canvas, -details, -embed, -figure, -figcaption, -footer, -header, -hgroup, -menu, -nav, -output, -ruby, -section, -summary, -time, -mark, -audio, -video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -menu, -nav, -section { - display: block; -} -body { - line-height: 1; -} -ol, -ul { - list-style: none; -} -blockquote, -q { - quotes: none; -} -blockquote:before, -blockquote:after, -q:before, -q:after { - content: ""; - content: none; -} -table { - border-collapse: collapse; - border-spacing: 0; -} - -/* index.html css */ -body { - max-width: 100%; - display: flex; - flex-direction: column; -} -a { - text-decoration: none; - color: black; -} -* { - box-sizing: border-box; - - font-family: "Pretendard-Medium"; - font-weight: 400; -} diff --git a/week1/shoppingList/styles/card/style.css b/week1/shoppingList/styles/card/style.css deleted file mode 100644 index 2c4f86a..0000000 --- a/week1/shoppingList/styles/card/style.css +++ /dev/null @@ -1,49 +0,0 @@ -.card { - display: flex; - flex-direction: column; - align-items: center; - gap: 5px; - transition: all 0.2s ease-in-out; - width: 100%; -} - -.card:hover { - animation: 1s linear infinite hoverAni; -} - -.card p { - margin: 0; -} - -.card img:nth-child(2) { - border-radius: 100%; - padding: 3px; -} -.card img:nth-child(2):hover { - filter: opacity(0.2) drop-shadow(0 0 0 #ff0000); -} - -.card img:first-child { - width: 100%; - height: 240px; - object-fit: cover; - border-radius: 20px; -} - -@keyframes hoverAni { - 0% { - transform: scale(1); - } - 33% { - transform: scale(1.04); - } - 33% { - transform: scale(0.96); - } - 66% { - transform: scale(1.04); - } - 100% { - transform: scale(1); - } -} diff --git a/week1/shoppingList/styles/font/style.css b/week1/shoppingList/styles/font/style.css deleted file mode 100644 index 038ce98..0000000 --- a/week1/shoppingList/styles/font/style.css +++ /dev/null @@ -1,14 +0,0 @@ -.large { - font-family: "Pretendard-Bold"; - font-size: 32px; -} - -.medium { - font-family: "Pretendard-Medium"; - font-size: 24px; -} - -.small { - font-family: "Pretendard-Regular"; - font-size: 18px; -} diff --git a/week1/shoppingList/styles/footer/style.css b/week1/shoppingList/styles/footer/style.css deleted file mode 100644 index b3e6dfd..0000000 --- a/week1/shoppingList/styles/footer/style.css +++ /dev/null @@ -1,13 +0,0 @@ -.footer { - display: flex; - justify-content: center; - align-items: center; - background-color: aqua; - width: 100%; - height: 200px; - margin-top: 40px; -} - -.footer h2 { - color: white; -} diff --git a/week1/shoppingList/styles/header/style.css b/week1/shoppingList/styles/header/style.css deleted file mode 100644 index 4d30532..0000000 --- a/week1/shoppingList/styles/header/style.css +++ /dev/null @@ -1,12 +0,0 @@ -.header { - display: flex; - justify-content: space-between; - position: fixed; - width: 100%; - top: 0; - left: 0; - padding: 20px; - background-color: greenyellow; - font-family: "Pretendard-Bold"; - z-index: 10; -} diff --git a/week1/shoppingList/styles/main/style.css b/week1/shoppingList/styles/main/style.css deleted file mode 100644 index 520e0e1..0000000 --- a/week1/shoppingList/styles/main/style.css +++ /dev/null @@ -1,9 +0,0 @@ -.main { - display: flex; - flex-direction: column; - padding-left: 300px; -} - -.main section { - padding-top: 120px; -} diff --git a/week1/shoppingList/styles/nav/style.css b/week1/shoppingList/styles/nav/style.css deleted file mode 100644 index d6e6237..0000000 --- a/week1/shoppingList/styles/nav/style.css +++ /dev/null @@ -1,39 +0,0 @@ -.nav { - display: flex; - flex-direction: column; - align-items: center; - background-color: green; - position: fixed; - padding: 30px; - border-radius: 20px; - top: 40%; - left: 20px; -} - -.nav ul { - background-color: white; - list-style-type: none; - padding: 10px 0px; -} - -.nav li { - cursor: pointer; - text-align: center; -} - -.nav li a { - display: inline-block; - padding: 10px 60px; -} - -.nav li:hover { - background-color: aqua; - a { - color: white; - } -} - -.nav h2 { - color: white; - padding: 20px 0px; -} diff --git a/week1/shoppingList/styles/section/style.css b/week1/shoppingList/styles/section/style.css deleted file mode 100644 index 893caf0..0000000 --- a/week1/shoppingList/styles/section/style.css +++ /dev/null @@ -1,26 +0,0 @@ -section > div { - display: grid; - grid-template-columns: repeat(6, 1fr); - gap: 10px; - padding: 10px 0px; - - @media screen and (max-width: 1460px) { - grid-template-columns: repeat(5, 1fr); - } - @media screen and (max-width: 1260px) { - grid-template-columns: repeat(4, 1fr); - } - @media screen and (max-width: 1080px) { - grid-template-columns: repeat(3, 1fr); - } - @media screen and (max-width: 900px) { - grid-template-columns: repeat(2, 1fr); - } - @media screen and (max-width: 768px) { - grid-template-columns: repeat(1, 1fr); - - .card img:first-child { - width: 100%; - } - } -} diff --git a/week1/shoppingList/styles/slider/style.css b/week1/shoppingList/styles/slider/style.css deleted file mode 100644 index 2a123d4..0000000 --- a/week1/shoppingList/styles/slider/style.css +++ /dev/null @@ -1,35 +0,0 @@ -#box { - position: relative; - width: 80%; - height: 400px; - overflow: hidden; - place-self: end; -} - -#slider { - position: absolute; - top: 100px; - display: flex; - width: 100%; - height: 300px; - animation: 30s linear 0s infinite normal forwards running sliderAni; -} - -.slide { - width: 180px; - height: 200px; -} - -@keyframes sliderAni { - 0% { - transform: translateX(0); - } - - 50% { - transform: translateX(-200%); - } - - 100% { - transform: translateX(0); - } -} diff --git "a/week2/assets/contents/\354\203\201\354\235\230/img1.png" "b/week2/assets/contents/\354\203\201\354\235\230/img1.png" deleted file mode 100644 index b6629b1..0000000 Binary files "a/week2/assets/contents/\354\203\201\354\235\230/img1.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\203\201\354\235\230/img2.png" "b/week2/assets/contents/\354\203\201\354\235\230/img2.png" deleted file mode 100644 index 8748839..0000000 Binary files "a/week2/assets/contents/\354\203\201\354\235\230/img2.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\203\201\354\235\230/img3.png" "b/week2/assets/contents/\354\203\201\354\235\230/img3.png" deleted file mode 100644 index 320549a..0000000 Binary files "a/week2/assets/contents/\354\203\201\354\235\230/img3.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\203\201\354\235\230/img4.png" "b/week2/assets/contents/\354\203\201\354\235\230/img4.png" deleted file mode 100644 index 18d26b1..0000000 Binary files "a/week2/assets/contents/\354\203\201\354\235\230/img4.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\213\240\353\260\234/img1.png" "b/week2/assets/contents/\354\213\240\353\260\234/img1.png" deleted file mode 100644 index 8d8cdd7..0000000 Binary files "a/week2/assets/contents/\354\213\240\353\260\234/img1.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\213\240\353\260\234/img2.png" "b/week2/assets/contents/\354\213\240\353\260\234/img2.png" deleted file mode 100644 index 1fd4019..0000000 Binary files "a/week2/assets/contents/\354\213\240\353\260\234/img2.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\213\240\353\260\234/img3.png" "b/week2/assets/contents/\354\213\240\353\260\234/img3.png" deleted file mode 100644 index 1055bdb..0000000 Binary files "a/week2/assets/contents/\354\213\240\353\260\234/img3.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\213\240\353\260\234/img4.png" "b/week2/assets/contents/\354\213\240\353\260\234/img4.png" deleted file mode 100644 index 60ad82a..0000000 Binary files "a/week2/assets/contents/\354\213\240\353\260\234/img4.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img1.png" "b/week2/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img1.png" deleted file mode 100644 index 080febc..0000000 Binary files "a/week2/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img1.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img2.png" "b/week2/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img2.png" deleted file mode 100644 index 5b1429e..0000000 Binary files "a/week2/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img2.png" and /dev/null differ diff --git "a/week2/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img3.png" "b/week2/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img3.png" deleted file mode 100644 index cfe166f..0000000 Binary files "a/week2/assets/contents/\354\225\205\354\204\270\354\204\234\353\246\254/img3.png" and /dev/null differ diff --git "a/week2/assets/contents/\355\225\230\354\235\230/img1.png" "b/week2/assets/contents/\355\225\230\354\235\230/img1.png" deleted file mode 100644 index 6067525..0000000 Binary files "a/week2/assets/contents/\355\225\230\354\235\230/img1.png" and /dev/null differ diff --git "a/week2/assets/contents/\355\225\230\354\235\230/img2.png" "b/week2/assets/contents/\355\225\230\354\235\230/img2.png" deleted file mode 100644 index 823a470..0000000 Binary files "a/week2/assets/contents/\355\225\230\354\235\230/img2.png" and /dev/null differ diff --git "a/week2/assets/contents/\355\225\230\354\235\230/img3.png" "b/week2/assets/contents/\355\225\230\354\235\230/img3.png" deleted file mode 100644 index 30de1f4..0000000 Binary files "a/week2/assets/contents/\355\225\230\354\235\230/img3.png" and /dev/null differ diff --git a/week2/assets/header/shop.svg b/week2/assets/header/shop.svg deleted file mode 100644 index f2f87a9..0000000 --- a/week2/assets/header/shop.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/week2/assets/icons/close.svg b/week2/assets/icons/close.svg deleted file mode 100644 index 862cca5..0000000 --- a/week2/assets/icons/close.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/week2/assets/icons/close_black.svg b/week2/assets/icons/close_black.svg deleted file mode 100644 index 1ecc01b..0000000 --- a/week2/assets/icons/close_black.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/week2/assets/icons/like.svg b/week2/assets/icons/like.svg deleted file mode 100644 index 85c0a55..0000000 --- a/week2/assets/icons/like.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/week2/constants/index.js b/week2/constants/index.js deleted file mode 100644 index 2b677fc..0000000 --- a/week2/constants/index.js +++ /dev/null @@ -1,5 +0,0 @@ -export const GUIDE_MESSAGE = Object.freeze({ - ADDCART_CONFIRM: "장바구니에 추가하시겠습니까 ?", - ALREADY_EXIST_ALERT: "이미 장바구니에 존재합니다 !", - COMPLETE_BUY_ALERT: "구매 완료되었습니다 !", -}); diff --git a/week2/model/cart/buy.js b/week2/model/cart/buy.js deleted file mode 100644 index 7838a6c..0000000 --- a/week2/model/cart/buy.js +++ /dev/null @@ -1,75 +0,0 @@ -import { formatValue } from "../../utils/format.js"; -import { GUIDE_MESSAGE } from "../../constants/index.js"; - -const buybtn = document.getElementById("buy-btn"); -const buyConfirmBtn = document.getElementById("buy-modal_confirm-btn"); - -const modal = document.getElementById("buy-modal"); -const modalList = document.querySelector("#buy-modal ul"); -const exitModalBtn = document.getElementById("buy-modal_exit-btn"); -const totalAmount = document.getElementById("total_amount"); - -function handleBuyBtnClick() { - modal.style.display = "flex"; - - const checkList = JSON.parse(localStorage.getItem("checkList")); - // const list = JSON.parse(localStorage.getItem("list")); - - checkList.forEach((item) => { - const listItem = document.createElement("li"); - listItem.style.padding = "10px 0px"; - - const itemContainer = document.createElement("div"); - itemContainer.classList.add("buy-modal_item-container"); - - const img = document.createElement("img"); - img.src = item.imgUrl; - img.alt = "상품 이미지"; - img.classList.add("buy-modal_item-img"); - - const name = document.createElement("span"); - name.innerText = item.title; - - const value = document.createElement("span"); - value.innerText = item.value + "원"; - - itemContainer.append(img, name, value); - listItem.appendChild(itemContainer); - modalList.appendChild(listItem); - }); - - const sum = checkList.reduce( - (acc, cur) => acc + +cur.value.replaceAll(",", ""), - 0 - ); - totalAmount.innerText = `총 금액: ${formatValue(sum.toString())} 원`; -} - -function handleExitClick() { - modal.style.display = "none"; - - modalList.innerHTML = ""; -} - -function handleBuyConfirm() { - const list = JSON.parse(localStorage.getItem("list")); - const checkList = JSON.parse(localStorage.getItem("checkList")); - - const result = list.filter( - (item) => !checkList.some((checkItem) => checkItem.id === item.id) - ); - - alert(GUIDE_MESSAGE.COMPLETE_BUY_ALERT); - - localStorage.setItem("list", JSON.stringify(result)); - localStorage.setItem("checkList", JSON.stringify([])); - - modal.style.display = "none"; - modalList.innerHTML = ""; - - window.location.reload(); -} - -buybtn.addEventListener("click", handleBuyBtnClick); -exitModalBtn.addEventListener("click", handleExitClick); -buyConfirmBtn.addEventListener("click", handleBuyConfirm); diff --git a/week2/model/cart/check.js b/week2/model/cart/check.js deleted file mode 100644 index 5b4925d..0000000 --- a/week2/model/cart/check.js +++ /dev/null @@ -1,42 +0,0 @@ -const checkAllBtn = document.getElementById("check-all-btn"); -const checkboxs = document.querySelectorAll(".cart_table tr"); - -function handleAllChecked(e) { - const checked = e.target.checked; - const allCheckBox = document.querySelectorAll(".check_item") ?? []; - const storeList = JSON.parse(localStorage.getItem("list")); - - allCheckBox.forEach((input) => { - input.checked = checked; - }); - - localStorage.setItem("checkList", JSON.stringify(checked ? storeList : [])); -} - -function handleChecked(e, itemId) { - const checked = e.target.checked; - - const storeList = JSON.parse(localStorage.getItem("list")); - const storeCheckList = JSON.parse(localStorage.getItem("checkList")) ?? []; - - const checkedItem = storeList.find((item) => item.id === itemId); - - if (checked) { - storeCheckList.push(checkedItem); - } else { - const idx = storeCheckList.findIndex((item) => item.id === itemId); - storeCheckList.splice(idx, 1); - } - localStorage.setItem("checkList", JSON.stringify(storeCheckList)); -} - -checkAllBtn.addEventListener("change", (e) => handleAllChecked(e)); - -checkboxs.forEach((checkbox, idx) => { - if (idx === 0) return; - - const box = checkbox.children[0].querySelector("input"); - const id = checkbox.getAttribute("id"); - - box.addEventListener("change", (e) => handleChecked(e, id)); -}); diff --git a/week2/model/cart/deleteItem.js b/week2/model/cart/deleteItem.js deleted file mode 100644 index fb007a5..0000000 --- a/week2/model/cart/deleteItem.js +++ /dev/null @@ -1,15 +0,0 @@ -const tableItemBtn = document.querySelectorAll(".cart_table button"); -const list = JSON.parse(localStorage.getItem("list")); - -function handleDelete(id) { - const deleted = list.filter((item) => item.id !== id); - localStorage.setItem("list", JSON.stringify(deleted)); - - window.location.reload(); -} - -tableItemBtn.forEach((btn) => { - const id = btn.className.match(/\d+/); - - btn.addEventListener("click", () => handleDelete(id + "")); -}); diff --git a/week2/model/cart/getData.js b/week2/model/cart/getData.js deleted file mode 100644 index 1cbc028..0000000 --- a/week2/model/cart/getData.js +++ /dev/null @@ -1,48 +0,0 @@ -const list = JSON.parse(localStorage.getItem("list")); -const checkList = JSON.parse(localStorage.getItem("checkList")); - -const table = document.querySelector(".cart_table"); - -list.forEach((item) => { - const { id, title, value, category, imgUrl } = item; - - const tr = document.createElement("tr"); - tr.setAttribute("id", id); - - const checkBoxTd = document.createElement("td"); - const checkBox = document.createElement("input"); - - if (checkList?.some((item) => item.id === Number(id))) - checkBox.checked = true; // check가 되어있던 item이면 checked 상태로 - - checkBox.classList.add("check_item"); - checkBox.type = "checkbox"; - checkBoxTd.appendChild(checkBox); - - const imgTd = document.createElement("td"); - const img = document.createElement("img"); - img.src = imgUrl; - img.alt = "장바구니 아이템 이미지"; - img.classList.add("item_img"); - imgTd.appendChild(img); - - const valueTd = document.createElement("td"); - valueTd.innerText = value + "원"; - - const titleTd = document.createElement("td"); - titleTd.innerText = title; - - const categoryTd = document.createElement("td"); - categoryTd.innerText = category; - - const btnTd = document.createElement("td"); - const btn = document.createElement("button"); - btn.innerText = "삭제"; - btn.classList.add(`cart_delete_btn${id}`); - btn.classList.add("small-btn"); - btnTd.appendChild(btn); - - tr.append(checkBoxTd, imgTd, titleTd, valueTd, categoryTd, btnTd); - - table.appendChild(tr); -}); diff --git a/week2/model/clickesc.js b/week2/model/clickesc.js deleted file mode 100644 index b625f15..0000000 --- a/week2/model/clickesc.js +++ /dev/null @@ -1,13 +0,0 @@ -const modal = document.getElementById("buy-modal"); -const sidebar = document.getElementById("modal"); - -window.addEventListener("keypress", (e) => { - const { key } = e; - - if (key === "Escape") { - if (modal?.style.display === "flex") modal.style.display = "none"; - - if (sidebar?.style.transform === "translateX(0px)") - sidebar.style.transform = "translateX(200px)"; - } -}); diff --git a/week2/model/home/addCart.js b/week2/model/home/addCart.js deleted file mode 100644 index b13058a..0000000 --- a/week2/model/home/addCart.js +++ /dev/null @@ -1,34 +0,0 @@ -import { GUIDE_MESSAGE } from "../../constants/index.js"; -import { formatValue } from "../../utils/format.js"; - -export function handleAddCart(e, category, imgUrl) { - const ok = confirm(GUIDE_MESSAGE.ADDCART_CONFIRM); // confirm 텍스트 보여주기 - - if (!ok) return; - - const id = e.currentTarget.getAttribute("id"); - const [img, like, title, value] = e.currentTarget.children; // card 요소의 자식 요소 가져오기 - const list = JSON.parse(localStorage.getItem("list")) ?? []; - - if (list.some((item) => item.id === id)) { - // 이미 장바구니에 있는 item이면 alert 후 리턴 - alert(GUIDE_MESSAGE.ALREADY_EXIST_ALERT); - return; - } - - let convertedValue = ""; - - const tmp = value.innerText.replace("원", ""); // "원" 제거 - - convertedValue = formatValue(tmp); - - list.push({ - id, - title: title.innerText, - value: convertedValue, - category, - imgUrl, - }); - - localStorage.setItem("list", JSON.stringify(list)); -} diff --git a/week2/model/home/filter.js b/week2/model/home/filter.js deleted file mode 100644 index 1ceb5aa..0000000 --- a/week2/model/home/filter.js +++ /dev/null @@ -1,92 +0,0 @@ -import { SHOPPING_LIST } from "./store.js"; -import { handleAddCart } from "./addCart.js"; - -const listItem = document.querySelectorAll(".nav li"); -const content = document.getElementById("content-box"); -const title = document.getElementById("content-title"); -const slider = document.getElementById("slider"); - -title.innerText = "전체"; - -SHOPPING_LIST.forEach((item) => { - /* 메인 컨텐츠 */ - const { id, name, value, category, imgUrl } = item; - - const container = document.createElement("div"); - container.setAttribute("id", id); - container.classList.add("card"); - container.classList.add(`${category}`); - container.addEventListener("click", (e) => - handleAddCart(e, category, imgUrl) - ); - - const cardImg = document.createElement("img"); - cardImg.src = imgUrl; - cardImg.alt = "카드 이미지"; - - const likeImg = document.createElement("img"); - likeImg.src = "../assets/icons/like.svg"; - likeImg.width = "30"; - likeImg.alt = "좋아요 이미지"; - - const nameText = document.createElement("p"); - nameText.innerText = name; - - const valueText = document.createElement("p"); - valueText.innerText = value + "원"; - - container.append(cardImg, likeImg, nameText, valueText); - - content.appendChild(container); - - /* 슬라이더 컨텐츠 */ - const sliderCard = document.createElement("img"); - sliderCard.src = imgUrl; - sliderCard.alt = "배너 이미지"; - sliderCard.classList.add("slide"); - - slider.appendChild(sliderCard); -}); - -function handleClickNav(innerText) { - content.innerHTML = ""; - title.innerText = innerText; - - const filteredData = SHOPPING_LIST.filter((item) => - innerText === "전체" ? true : item.category === innerText - ); - - filteredData.forEach((item) => { - const { category, name, value, imgUrl } = item; - - const container = document.createElement("div"); - container.classList.add("card"); - container.addEventListener("click", (e) => - handleAddCart(e, category, imgUrl) - ); - - const cardImg = document.createElement("img"); - cardImg.src = imgUrl; - cardImg.alt = "상품 카드 이미지"; - - const likeImg = document.createElement("img"); - likeImg.src = "../assets/icons/like.svg"; - likeImg.alt = "좋아요 이미지"; - likeImg.width = "30"; - - const nameText = document.createElement("p"); - nameText.innerText = name; - - const valueText = document.createElement("p"); - valueText.innerText = value + "원"; - - container.append(cardImg, likeImg, nameText, valueText); - - content.appendChild(container); - }); -} - -listItem.forEach((item) => { - const category = item.innerText; - item.addEventListener("click", () => handleClickNav(category)); -}); diff --git a/week2/model/home/modal.js b/week2/model/home/modal.js deleted file mode 100644 index edb51c0..0000000 --- a/week2/model/home/modal.js +++ /dev/null @@ -1,15 +0,0 @@ -const openBtn = document.getElementById("open-modal"); -const exitBtn = document.getElementById("exit-modal"); - -const modal = document.getElementById("modal"); - -function handleOpen() { - modal.style.transform = "translateX(0)"; -} - -function handleExit() { - modal.style.transform = "translateX(200px)"; -} - -openBtn.addEventListener("click", handleOpen); -exitBtn.addEventListener("click", handleExit); diff --git a/week2/model/home/store.js b/week2/model/home/store.js deleted file mode 100644 index 6d7a572..0000000 --- a/week2/model/home/store.js +++ /dev/null @@ -1,79 +0,0 @@ -export const SHOPPING_LIST = [ - { - id: 1, - name: "화이트 자켓", - category: "상의", - value: 23000, - imgUrl: "../assets/contents/상의/img1.png", - }, - { - id: 2, - name: "맨투맨", - category: "상의", - value: 18000, - imgUrl: "../assets/contents/상의/img2.png", - }, - { - id: 3, - name: "바람막이", - category: "상의", - value: 22000, - imgUrl: "../assets/contents/상의/img3.png", - }, - { - id: 4, - name: "셔츠", - category: "상의", - value: 20000, - imgUrl: "../assets/contents/상의/img4.png", - }, - { - id: 5, - name: "핀턱 코튼 와이드 팬츠", - category: "하의", - value: 50000, - imgUrl: "../assets/contents/하의/img1.png", - }, - { - id: 6, - name: "크로스 트레이닝 팬츠", - category: "하의", - value: 42000, - imgUrl: "../assets/contents/하의/img2.png", - }, - { - id: 7, - name: "블랙 와이드 팬츠", - category: "하의", - value: 39000, - imgUrl: "../assets/contents/하의/img3.png", - }, - { - id: 8, - name: "더비 슈즈", - category: "신발", - value: 104000, - imgUrl: "../assets/contents/신발/img1.png", - }, - { - id: 9, - name: "패디드 슬리퍼", - category: "신발", - value: 35000, - imgUrl: "../assets/contents/신발/img2.png", - }, - { - id: 10, - name: "플립 플롭", - category: "신발", - value: 22000, - imgUrl: "../assets/contents/신발/img3.png", - }, - { - id: 11, - name: "어그 부츠", - category: "신발", - value: 60000, - imgUrl: "../assets/contents/신발/img4.png", - }, -]; diff --git a/week2/model/redirect.js b/week2/model/redirect.js deleted file mode 100644 index 51b2eec..0000000 --- a/week2/model/redirect.js +++ /dev/null @@ -1,25 +0,0 @@ -/* cart 페이지 */ -const homeBtn = document.getElementById("home-btn"); - -homeBtn?.addEventListener("click", () => { - // home.html 에선 homeBtn이 없으므로 에러. 따라서 옵셔널 체이닝 사용 - window.location.href = "home.html"; -}); - -const mainLogo = document.getElementById("main_logo"); - -function handleGoHome() { - window.location.href = "home.html"; -} - -mainLogo.addEventListener("click", handleGoHome); - -const cartText = document.getElementById("modal_cart-text"); - -/* home 페이지 */ - -function handleGoCart() { - window.location.href = "cart.html"; -} - -cartText.addEventListener("click", handleGoCart); diff --git a/week2/pages/cart.html b/week2/pages/cart.html deleted file mode 100644 index e422017..0000000 --- a/week2/pages/cart.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - 주용이의 쇼핑몰 - - -
- -

장바구니 페이지

- 메뉴 이미지 -
- - - -

- -
-
-
- - - - - - - - -
상품 정보상품 금액카테고리비고
-
-
- - -
-
- - - - - - - - - - diff --git a/week2/pages/home.html b/week2/pages/home.html deleted file mode 100644 index 0e9f08b..0000000 --- a/week2/pages/home.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - 주용이의 쇼핑몰 - - -
- -

주용이의 쇼핑몰

- 메뉴 이미지 -
-
-
-
-
-
-

-
-
-
- - - 닫힘 버튼 이미지 - - - - - - - - - - diff --git a/week2/styles/card/style.css b/week2/styles/card/style.css deleted file mode 100644 index 2c4f86a..0000000 --- a/week2/styles/card/style.css +++ /dev/null @@ -1,49 +0,0 @@ -.card { - display: flex; - flex-direction: column; - align-items: center; - gap: 5px; - transition: all 0.2s ease-in-out; - width: 100%; -} - -.card:hover { - animation: 1s linear infinite hoverAni; -} - -.card p { - margin: 0; -} - -.card img:nth-child(2) { - border-radius: 100%; - padding: 3px; -} -.card img:nth-child(2):hover { - filter: opacity(0.2) drop-shadow(0 0 0 #ff0000); -} - -.card img:first-child { - width: 100%; - height: 240px; - object-fit: cover; - border-radius: 20px; -} - -@keyframes hoverAni { - 0% { - transform: scale(1); - } - 33% { - transform: scale(1.04); - } - 33% { - transform: scale(0.96); - } - 66% { - transform: scale(1.04); - } - 100% { - transform: scale(1); - } -} diff --git a/week2/styles/cart/main.css b/week2/styles/cart/main.css deleted file mode 100644 index 6a50f4d..0000000 --- a/week2/styles/cart/main.css +++ /dev/null @@ -1,12 +0,0 @@ -.btn-wrapper { - display: flex; - gap: 12px; - padding: 20px 0px; -} - -#total_amount { - height: 10%; - display: flex; - align-items: center; - font-family: "Pretendard-Bold"; -} diff --git a/week2/styles/cart/modal.css b/week2/styles/cart/modal.css deleted file mode 100644 index 90f5884..0000000 --- a/week2/styles/cart/modal.css +++ /dev/null @@ -1,49 +0,0 @@ -#buy-modal { - display: none; - flex-direction: column; - align-items: center; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 10; - margin: auto auto; - padding: 20px 0px; - max-width: 50%; - max-height: 60%; - box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); - background-color: white; - border-radius: 32px; -} - -#buy-modal h1 { - font-family: "Pretendard-Bold"; - font-size: 32px; -} -#buy-modal ul { - width: 80%; - height: 80%; - padding: 10px; - overflow-y: scroll; - overscroll-behavior-y: contain; - font-family: "Pretendard-Medium"; -} - -#buy-modal_exit-btn { - cursor: pointer; - position: absolute; - left: 20px; -} - -.buy-modal_item-container { - display: flex; - justify-content: space-between; - align-items: center; -} - -.buy-modal_item-img { - width: 50px; - height: 50px; - border-radius: 20px; -} diff --git a/week2/styles/cart/table.css b/week2/styles/cart/table.css deleted file mode 100644 index 47244a6..0000000 --- a/week2/styles/cart/table.css +++ /dev/null @@ -1,39 +0,0 @@ -.cart_main { - display: flex; - flex-direction: column; - align-items: center; - - padding-top: 180px; -} - -.cart_content { - display: flex; - flex-direction: column; - align-items: center; - - width: 70%; - height: 600px; - overflow-y: scroll; -} - -.cart_table { - width: 90%; -} - -.cart_table td, -.cart_table th { - padding: 10px; - text-align: center; - vertical-align: middle; - border: 1px solid black; -} - -.cart_table th { - background-color: antiquewhite; -} - -.cart_table .item_img { - width: 50px; - height: 50px; - object-fit: cover; -} diff --git a/week2/styles/font/style.css b/week2/styles/font/style.css deleted file mode 100644 index 038ce98..0000000 --- a/week2/styles/font/style.css +++ /dev/null @@ -1,14 +0,0 @@ -.large { - font-family: "Pretendard-Bold"; - font-size: 32px; -} - -.medium { - font-family: "Pretendard-Medium"; - font-size: 24px; -} - -.small { - font-family: "Pretendard-Regular"; - font-size: 18px; -} diff --git a/week2/styles/footer/style.css b/week2/styles/footer/style.css deleted file mode 100644 index b3e6dfd..0000000 --- a/week2/styles/footer/style.css +++ /dev/null @@ -1,13 +0,0 @@ -.footer { - display: flex; - justify-content: center; - align-items: center; - background-color: aqua; - width: 100%; - height: 200px; - margin-top: 40px; -} - -.footer h2 { - color: white; -} diff --git a/week2/styles/header/style.css b/week2/styles/header/style.css deleted file mode 100644 index ba33af1..0000000 --- a/week2/styles/header/style.css +++ /dev/null @@ -1,20 +0,0 @@ -.header { - display: flex; - justify-content: space-between; - position: fixed; - width: 100%; - top: 0; - left: 0; - padding: 20px; - background-color: greenyellow; - font-family: "Pretendard-Bold"; - z-index: 10; -} - -#open-modal { - cursor: pointer; -} - -#main_logo { - cursor: pointer; -} diff --git a/week2/styles/main/style.css b/week2/styles/main/style.css deleted file mode 100644 index 520e0e1..0000000 --- a/week2/styles/main/style.css +++ /dev/null @@ -1,9 +0,0 @@ -.main { - display: flex; - flex-direction: column; - padding-left: 300px; -} - -.main section { - padding-top: 120px; -} diff --git a/week2/styles/modal/style.css b/week2/styles/modal/style.css deleted file mode 100644 index e2a826f..0000000 --- a/week2/styles/modal/style.css +++ /dev/null @@ -1,31 +0,0 @@ -#modal { - width: 200px; - height: 80%; - padding: 20px; - background-color: green; - position: fixed; - right: 0; - top: 100px; - border-top-left-radius: 30px; - border-bottom-left-radius: 30px; - - transform: translateX(200px); - transition: all 0.3s ease-in-out; -} - -#modal ul { - font-family: "Pretendard-Medium"; - margin-top: 40px; - color: white; -} - -#modal li { - text-align: center; - padding: 6px 0px; - cursor: pointer; -} - -#modal li:hover { - background-color: white; - color: black; -} diff --git a/week2/styles/nav/style.css b/week2/styles/nav/style.css deleted file mode 100644 index 48640c7..0000000 --- a/week2/styles/nav/style.css +++ /dev/null @@ -1,34 +0,0 @@ -.nav { - display: flex; - flex-direction: column; - align-items: center; - background-color: green; - position: fixed; - padding: 30px; - border-radius: 20px; - top: 40%; - left: 20px; -} - -.nav ul { - background-color: white; - list-style-type: none; -} - -.nav li { - cursor: pointer; - text-align: center; - padding: 10px 48px; -} - -.nav li:hover { - background-color: aqua; - a { - color: white; - } -} - -.nav h2 { - color: white; - padding: 20px 0px; -} diff --git a/week2/styles/section/style.css b/week2/styles/section/style.css deleted file mode 100644 index 973226f..0000000 --- a/week2/styles/section/style.css +++ /dev/null @@ -1,34 +0,0 @@ -section > div { - display: grid; - grid-template-columns: repeat(6, 1fr); - gap: 10px; - padding: 10px 0px; - - @media screen and (max-width: 1460px) { - grid-template-columns: repeat(5, 1fr); - } - @media screen and (max-width: 1260px) { - grid-template-columns: repeat(4, 1fr); - } - @media screen and (max-width: 1080px) { - grid-template-columns: repeat(3, 1fr); - } - @media screen and (max-width: 900px) { - grid-template-columns: repeat(2, 1fr); - } - @media screen and (max-width: 768px) { - grid-template-columns: repeat(1, 1fr); - - .card img:first-child { - width: 100%; - } - } -} - -.hidden { - display: none; -} - -.show { - display: block; -} diff --git a/week2/styles/slider/style.css b/week2/styles/slider/style.css deleted file mode 100644 index 2a123d4..0000000 --- a/week2/styles/slider/style.css +++ /dev/null @@ -1,35 +0,0 @@ -#box { - position: relative; - width: 80%; - height: 400px; - overflow: hidden; - place-self: end; -} - -#slider { - position: absolute; - top: 100px; - display: flex; - width: 100%; - height: 300px; - animation: 30s linear 0s infinite normal forwards running sliderAni; -} - -.slide { - width: 180px; - height: 200px; -} - -@keyframes sliderAni { - 0% { - transform: translateX(0); - } - - 50% { - transform: translateX(-200%); - } - - 100% { - transform: translateX(0); - } -} diff --git a/week2/styles/style.css b/week2/styles/style.css deleted file mode 100644 index aaaee46..0000000 --- a/week2/styles/style.css +++ /dev/null @@ -1,171 +0,0 @@ -@font-face { - font-family: "Pretendard-Regular"; - src: url("https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff") - format("woff"); - font-weight: 400; - font-style: normal; -} -@font-face { - font-family: "Pretendard-Medium"; - src: url("https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Medium.woff") - format("woff"); - font-weight: 500; - font-style: normal; -} -@font-face { - font-family: "Pretendard-Bold"; - src: url("https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Bold.woff") - format("woff"); - font-weight: 600; - font-style: normal; -} - -/* reset css */ -html, -body, -div, -span, -applet, -object, -iframe, -h1, -h2, -h3, -h4, -h5, -h6, -p, -blockquote, -pre, -a, -abbr, -acronym, -address, -big, -cite, -code, -del, -dfn, -em, -img, -ins, -kbd, -q, -s, -samp, -small, -strike, -strong, -sub, -sup, -tt, -var, -b, -u, -i, -center, -dl, -dt, -dd, -ol, -ul, -li, -fieldset, -form, -label, -legend, -table, -caption, -tbody, -tfoot, -thead, -tr, -th, -td, -article, -aside, -canvas, -details, -embed, -figure, -figcaption, -footer, -header, -hgroup, -menu, -nav, -output, -ruby, -section, -summary, -time, -mark, -audio, -video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -menu, -nav, -section { - display: block; -} -body { - line-height: 1; -} -ol, -ul { - list-style: none; -} -blockquote, -q { - quotes: none; -} -blockquote:before, -blockquote:after, -q:before, -q:after { - content: ""; - content: none; -} -table { - border-collapse: collapse; - border-spacing: 0; -} - -/* index.html css */ -body { - max-width: 100%; - display: flex; - flex-direction: column; -} -a { - text-decoration: none; - color: black; -} -* { - box-sizing: border-box; - - font-family: "Pretendard-Medium"; - font-weight: 400; -} - -.small-btn { - cursor: pointer; - padding: 8px 16px; - border-radius: 12px; - border: 1px solid darkgray; - background-color: transparent; -} diff --git a/week2/utils/format.js b/week2/utils/format.js deleted file mode 100644 index dc4d835..0000000 --- a/week2/utils/format.js +++ /dev/null @@ -1,16 +0,0 @@ -export const formatValue = (value) => { - let converted = ""; - value - .split("") - .reverse() - .forEach((char, idx) => { - // 가격 배열을 거꾸로 순회하며 3번째마다 "," 추가 - if (idx % 3 === 0 && idx !== 0) { - converted += "," + char; - return; - } - converted += char; - }); - - return converted.split("").reverse().join(""); -}; diff --git a/week4/.babelrc b/week4/.babelrc new file mode 100644 index 0000000..d4e0a74 --- /dev/null +++ b/week4/.babelrc @@ -0,0 +1,9 @@ +{ + "presets": [ + ["@babel/preset-env"], + "@babel/preset-typescript", + "@babel/preset-react", + "@emotion/babel-preset-css-prop" + ], + "plugins": ["@emotion"] +} diff --git a/week4/.eslintrc.cjs b/week4/.eslintrc.cjs new file mode 100644 index 0000000..6e8698b --- /dev/null +++ b/week4/.eslintrc.cjs @@ -0,0 +1,18 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react-hooks/recommended", + ], + ignorePatterns: ["dist", ".eslintrc.cjs"], + parser: "@typescript-eslint/parser", + plugins: ["react-refresh"], + rules: { + "react-refresh/only-export-components": [ + "warn", + { allowConstantExport: true }, + ], + }, +}; diff --git a/week4/.gitignore b/week4/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/week4/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/week4/README.md b/week4/README.md new file mode 100644 index 0000000..0d6babe --- /dev/null +++ b/week4/README.md @@ -0,0 +1,30 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js +export default { + // other rules... + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: ['./tsconfig.json', './tsconfig.node.json'], + tsconfigRootDir: __dirname, + }, +} +``` + +- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` +- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list diff --git a/week4/index.html b/week4/index.html new file mode 100644 index 0000000..e4b78ea --- /dev/null +++ b/week4/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/week4/package.json b/week4/package.json new file mode 100644 index 0000000..3141a67 --- /dev/null +++ b/week4/package.json @@ -0,0 +1,41 @@ +{ + "name": "week4", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "axios": "^1.6.8", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-error-boundary": "^4.0.13", + "react-hook-form": "^7.51.3", + "react-router-dom": "^6.23.0" + }, + "devDependencies": { + "@babel/core": "^7.24.4", + "@babel/preset-env": "^7.24.4", + "@babel/preset-react": "^7.24.1", + "@babel/preset-typescript": "^7.24.1", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/babel-preset-css-prop": "^11.11.0", + "@types/react": "^18.2.66", + "@types/react-dom": "^18.2.22", + "@typescript-eslint/eslint-plugin": "^7.2.0", + "@typescript-eslint/parser": "^7.2.0", + "@vitejs/plugin-react-swc": "^3.5.0", + "eslint": "^8.57.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.6", + "typescript": "^5.2.2", + "vite": "^5.2.0", + "vite-tsconfig-paths": "^4.3.2" + } +} diff --git a/week4/src/App.tsx b/week4/src/App.tsx new file mode 100644 index 0000000..eab46c9 --- /dev/null +++ b/week4/src/App.tsx @@ -0,0 +1,27 @@ +import { Global, ThemeProvider, css } from "@emotion/react"; +import { Outlet } from "react-router-dom"; +import { Theme } from "@styles/theme"; +import { GlobalStyle } from "@styles/GlobalStyle"; + +const MainCenterView = css({ + width: "100vw", + height: "100vh", + display: "flex", + justifyContent: "center", + alignItems: "center", +}); + +function App() { + return ( + <> + + +
+ +
+
+ + ); +} + +export default App; diff --git a/week4/src/api/axiosInstance.ts b/week4/src/api/axiosInstance.ts new file mode 100644 index 0000000..1c6da4e --- /dev/null +++ b/week4/src/api/axiosInstance.ts @@ -0,0 +1,8 @@ +import axios from "axios"; +import { checkMemberId } from "./interceptors"; + +export const axiosInstance = axios.create({ + baseURL: "http://34.64.233.12:8080", +}); + +axiosInstance.interceptors.request.use(checkMemberId); diff --git a/week4/src/api/index.ts b/week4/src/api/index.ts new file mode 100644 index 0000000..fd71e23 --- /dev/null +++ b/week4/src/api/index.ts @@ -0,0 +1,35 @@ +import { END_POINTS } from "@/constants/api"; +import { axiosInstance } from "./axiosInstance"; +import { ChangePwdType, UserDataType } from "@/types/api"; + +export const postSignUp = async (formData: UserDataType) => { + const { data } = await axiosInstance.post( + END_POINTS.SIGN_UP, + formData + ); + + return data; +}; + +export const getMemberInfo = async () => { + const { data } = await axiosInstance.get(END_POINTS.USER_INFO); + + return data; +}; + +type PostLoginType = Omit; + +export const postLogin = async (formData: PostLoginType) => { + const { data, headers } = await axiosInstance.post( + END_POINTS.LOGIN, + formData + ); + + return { data, headers }; +}; + +export const patchPassword = async (formData: ChangePwdType) => { + const { data } = await axiosInstance.patch(END_POINTS.CHANGE_PWD, formData); + + return data; +}; diff --git a/week4/src/api/interceptors.ts b/week4/src/api/interceptors.ts new file mode 100644 index 0000000..dd05af9 --- /dev/null +++ b/week4/src/api/interceptors.ts @@ -0,0 +1,13 @@ +import { InternalAxiosRequestConfig } from "axios"; + +export const checkMemberId = (config: InternalAxiosRequestConfig) => { + const memberId = localStorage.getItem("memberId"); + + if (!memberId) return config; + + if (config.method === "get" || config.method === "patch") { + config.headers.memberId = memberId; + } + + return config; +}; diff --git a/week4/src/assets/Example.mp4 b/week4/src/assets/Example.mp4 new file mode 100644 index 0000000..901c9ca Binary files /dev/null and b/week4/src/assets/Example.mp4 differ diff --git a/week1/shoppingList/assets/header/menu.svg b/week4/src/assets/down.svg similarity index 56% rename from week1/shoppingList/assets/header/menu.svg rename to week4/src/assets/down.svg index ea05b8c..a35a3fb 100644 --- a/week1/shoppingList/assets/header/menu.svg +++ b/week4/src/assets/down.svg @@ -1,3 +1,3 @@ - + diff --git a/week4/src/assets/img.jpeg b/week4/src/assets/img.jpeg new file mode 100644 index 0000000..efd5a3a Binary files /dev/null and b/week4/src/assets/img.jpeg differ diff --git a/week2/assets/header/menu.svg b/week4/src/assets/up.svg similarity index 56% rename from week2/assets/header/menu.svg rename to week4/src/assets/up.svg index ea05b8c..e56de61 100644 --- a/week2/assets/header/menu.svg +++ b/week4/src/assets/up.svg @@ -1,3 +1,3 @@ - + diff --git a/week4/src/components/Signup/Signup.style.ts b/week4/src/components/Signup/Signup.style.ts new file mode 100644 index 0000000..8215052 --- /dev/null +++ b/week4/src/components/Signup/Signup.style.ts @@ -0,0 +1,13 @@ +import { Theme } from "@/styles/theme"; +import { css } from "@emotion/react"; + +export const formStyle = css({ + display: "flex", + flexDirection: "column", + alignItems: "center", + gap: Theme.spacing.spacing4, + + "& div": { + width: "100%", + }, +}); diff --git a/week4/src/components/Signup/SignupForm.tsx b/week4/src/components/Signup/SignupForm.tsx new file mode 100644 index 0000000..1321171 --- /dev/null +++ b/week4/src/components/Signup/SignupForm.tsx @@ -0,0 +1,113 @@ +import { GUIDE_MESSAGE } from "@/constants/message"; +import { UserDataType } from "@/types/api"; +import { FormEvent, HTMLAttributes, useEffect, useState } from "react"; +import { + UseFormRegister, + UseFormSetFocus, + UseFormWatch, +} from "react-hook-form"; +import Button from "../common/Button/Button"; +import Flex from "../common/Flex/Flex"; +import Input from "../common/Input/Input"; +import { formStyle } from "./Signup.style"; + +interface SignUpFormProps + extends Omit, "onFocus"> { + register: UseFormRegister; + onWatch: UseFormWatch; + onGoBack: () => void; + onFocus: UseFormSetFocus; +} + +type formType = "authenticationId" | "password" | "nickname" | "phone"; + +const SignUpForm = ({ + register, + onWatch, + onSubmit, + onGoBack, + onFocus, +}: SignUpFormProps) => { + const [phoneNum, setPhoneNum] = useState(""); + const { ref, name, onChange } = register("phone"); + const [errorInput, setErrorInput] = useState(); + + /** 전화번호 '-' 자동완성 */ + useEffect(() => { + if (phoneNum.length === 11) { + setPhoneNum((prev) => prev.replace(/(\d{3})(\d{4})(\d{4})/, "$1-$2-$3")); + } + }, [phoneNum]); + + /** 빈 Input 요소 onFocus */ + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + const watchList: formType[] = [ + "authenticationId", + "password", + "nickname", + "phone", + ]; + let isError = false; + + watchList.forEach((data) => { + if (!onWatch(data) && !isError) { + setErrorInput(data); + onFocus(data); + isError = true; + return; + } + }); + + onSubmit?.(e); + }; + + return ( +
+ + + + { + onChange(e); + setPhoneNum(e.target.value); + }} + size="large" + label="전화번호" + isError={!onWatch("phone") && errorInput === "phone"} + supportingText={GUIDE_MESSAGE.PHONENUM} + /> + + + + +
+ ); +}; + +export default SignUpForm; diff --git a/week4/src/components/common/Box/Box.style.ts b/week4/src/components/common/Box/Box.style.ts new file mode 100644 index 0000000..6ee4a13 --- /dev/null +++ b/week4/src/components/common/Box/Box.style.ts @@ -0,0 +1,72 @@ +import { css } from "@emotion/react"; + +export interface BoxStyleProps { + position?: + | "static" + | "relative" + | "absolute" + | "fixed" + | "sticky" + | "inherit"; + width?: string; + height?: string; + margin?: string; + marginRight?: string; + marginTop?: string; + marginLeft?: string; + marginBottom?: string; + padding?: string; + paddingTop?: string; + paddingRight?: string; + paddingBottom?: string; + paddingLeft?: string; + border?: string; + borderRadius?: string; + borderColor?: string; + boxShadow?: string; + backgroundColor?: string; + color?: string; +} + +export const getBoxStyle = ({ + position = "static", + width = "", + height = "", + margin = "0", + marginRight = "", + marginTop = "", + marginLeft = "", + marginBottom = "", + padding = "", + paddingTop = "", + paddingRight = "", + paddingBottom = "", + paddingLeft = "", + border = "", + borderRadius = "", + borderColor = "", + boxShadow = "", + backgroundColor = "", + color = "", +}: BoxStyleProps) => + css({ + position, + width, + height, + margin, + marginRight, + marginTop, + marginLeft, + marginBottom, + padding, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + border, + borderRadius, + borderColor, + boxShadow: boxShadow, + backgroundColor, + color, + }); diff --git a/week4/src/components/common/Box/Box.tsx b/week4/src/components/common/Box/Box.tsx new file mode 100644 index 0000000..cb801f1 --- /dev/null +++ b/week4/src/components/common/Box/Box.tsx @@ -0,0 +1,14 @@ +import { ElementType } from "react"; +import { BoxStyleProps, getBoxStyle } from "./Box.style"; + +interface BoxProps extends React.HTMLAttributes { + tag?: ElementType; + styles?: BoxStyleProps; +} + +const Box = ({ tag = "div", styles = {}, children }: BoxProps) => { + const Tag = tag; + return {children}; +}; + +export default Box; diff --git a/week4/src/components/common/Button/Button.style.ts b/week4/src/components/common/Button/Button.style.ts new file mode 100644 index 0000000..68ff8ae --- /dev/null +++ b/week4/src/components/common/Button/Button.style.ts @@ -0,0 +1,92 @@ +import { css } from "@emotion/react"; + +import { Theme } from "@styles/theme"; + +export const variantStyle = { + primary: css({ + backgroundColor: Theme.color.blue800, + color: Theme.color.white, + + "&:hover:enabled": { + backgroundColor: Theme.color.blue900, + }, + }), + + secondary: css({ + backgroundColor: Theme.color.gray600, + color: Theme.color.white, + + "&:hover:enabled": { + backgroundColor: Theme.color.gray400, + }, + }), + + outline: css({ + backgroundColor: Theme.color.white, + color: Theme.color.gray800, + + boxShadow: `inset 0 0 0 1.5px ${Theme.color.gray200}`, + + "&:hover:enabled": { + backgroundColor: Theme.color.gray100, + }, + }), + + default: css({ + backgroundColor: Theme.color.black, + color: Theme.color.white, + + "&:hover:enabled": { + backgroundColor: Theme.color.blue900, + }, + }), +}; + +export const sizeStyle = { + xLarge: css({ + padding: "16px 64px", + fontSize: Theme.text.large.fontSize, + lineHeight: Theme.text.large.lineHeight, + }), + + large: css({ + padding: "14px 32px", + fontSize: Theme.text.medium.fontSize, + lineHeight: Theme.text.medium.lineHeight, + }), + + medium: css({ + padding: "12px 18px", + fontSize: Theme.text.medium.fontSize, + lineHeight: Theme.text.medium.lineHeight, + }), + + small: css({ + padding: "8px 12px", + fontSize: Theme.text.small.fontSize, + lineHeight: Theme.text.small.lineHeight, + }), +}; + +export const buttonStyle = css({ + display: "flex", + justifyContent: "center", + alignItems: "center", + gap: "6px", + + border: "none", + borderRadius: Theme.borderRadius.medium, + + backgroundColor: "white", + + cursor: "pointer", + + fontWeight: 600, + + transition: "all .2s ease-in-out", + + "& svg": { + width: "18px", + height: "18px", + }, +}); diff --git a/week4/src/components/common/Button/Button.tsx b/week4/src/components/common/Button/Button.tsx new file mode 100644 index 0000000..bcfd36c --- /dev/null +++ b/week4/src/components/common/Button/Button.tsx @@ -0,0 +1,40 @@ +import { ComponentPropsWithRef, ReactNode } from "react"; + +import { + buttonStyle, + sizeStyle, + variantStyle, +} from "@components/common/Button/Button.style"; + +import { SizeType } from "@/types/size"; + +export interface IButton extends ComponentPropsWithRef<"button"> { + variant?: "primary" | "secondary" | "outline" | "default"; + size?: Extract; + children: ReactNode; +} + +const Button = ({ + variant = "default", + size = "medium", + ...props +}: IButton) => { + const handleKeyDown = (e: React.KeyboardEvent) => { + const { key } = e; + if (key === "Enter") { + props?.onClick; + } + }; + return ( + + ); +}; + +export default Button; diff --git a/week4/src/components/common/Flex/Flex.style.ts b/week4/src/components/common/Flex/Flex.style.ts new file mode 100644 index 0000000..654635b --- /dev/null +++ b/week4/src/components/common/Flex/Flex.style.ts @@ -0,0 +1,114 @@ +import { css } from "@emotion/react"; + +export interface FlexStyleProps { + position?: + | "static" + | "absolute" + | "relative" + | "fixed" + | "sticky" + | "inherit"; + + wrap?: "nowrap" | "wrap" | "wrap-reverse" | "inherit" | "initial"; + basis?: 0 | "auto" | "200px"; + grow?: string; + shrink?: string; + + direction?: "row" | "column"; + + align?: + | "normal" + | "normal" + | "stretch" + | "center" + | "start" + | "end" + | "flex-start" + | "flex-end" + | "self-start" + | "self-end" + | "baseline" + | "inherit" + | "initial" + | "unset"; + justify?: + | "center" + | "start" + | "flex-start" + | "end" + | "flex-end" + | "left" + | "right" + | "normal" + | "space-between" + | "space-around" + | "space-evenly" + | "stretch" + | "inherit" + | "initial" + | "revert" + | "unset"; + gap?: string; + + width?: string; + height?: string; + + margin?: string; + marginRight?: string; + marginTop?: string; + marginLeft?: string; + marginBottom?: string; + padding?: string; + paddingTop?: string; + paddingRight?: string; + paddingBottom?: string; + paddingLeft?: string; +} + +export const getFlexStyle = ({ + position = "static", + wrap = "nowrap", + basis = "auto", + grow = "1", + shrink = "0", + direction = "row", + align = "flex-start", + justify = "flex-start", + gap = "0px", + width = "", + height = "", + margin = "0", + marginRight = "", + marginTop = "", + marginLeft = "", + marginBottom = "", + padding = "", + paddingTop = "", + paddingRight = "", + paddingBottom = "", + paddingLeft = "", +}: FlexStyleProps) => + css({ + display: "flex", + position, + flexWrap: wrap, + flexBasis: basis, + flexGrow: grow, + flexShrink: shrink, + flexDirection: direction, + alignItems: align, + justifyContent: justify, + gap, + width, + height, + margin, + marginRight, + marginLeft, + marginTop, + marginBottom, + padding, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + }); diff --git a/week4/src/components/common/Flex/Flex.tsx b/week4/src/components/common/Flex/Flex.tsx new file mode 100644 index 0000000..d65b6e5 --- /dev/null +++ b/week4/src/components/common/Flex/Flex.tsx @@ -0,0 +1,19 @@ +import { ElementType } from "react"; +import { FlexStyleProps, getFlexStyle } from "./Flex.style"; + +interface FlexProps extends React.HTMLAttributes { + tag?: ElementType; + styles?: FlexStyleProps; +} + +const Flex = ({ tag = "div", styles = {}, children, ...props }: FlexProps) => { + const Tag = tag; + + return ( + + {children} + + ); +}; + +export default Flex; diff --git a/week4/src/components/common/Heading/Heading.style.ts b/week4/src/components/common/Heading/Heading.style.ts new file mode 100644 index 0000000..46400b8 --- /dev/null +++ b/week4/src/components/common/Heading/Heading.style.ts @@ -0,0 +1,41 @@ +import { css } from "@emotion/react"; + +import { Theme } from "@styles/theme"; + +import { IHeading } from "./Heading"; + +export const headingStyle = (size: Required["size"]) => { + const heading = { + xxLarge: css({ + fontSize: Theme.heading.xxLarge.fontSize, + lineHeight: Theme.heading.xxLarge.lineHeight, + }), + + xLarge: css({ + fontSize: Theme.heading.xLarge.fontSize, + lineHeight: Theme.heading.xLarge.lineHeight, + }), + + large: css({ + fontSize: Theme.heading.large.fontSize, + lineHeight: Theme.heading.large.lineHeight, + }), + + medium: css({ + fontSize: Theme.heading.medium.fontSize, + lineHeight: Theme.heading.medium.lineHeight, + }), + + small: css({ + fontSize: Theme.heading.small.fontSize, + lineHeight: Theme.heading.small.lineHeight, + }), + + xSmall: css({ + fontSize: Theme.heading.xSmall.fontSize, + lineHeight: Theme.heading.xSmall.lineHeight, + }), + }; + + return heading[size]; +}; diff --git a/week4/src/components/common/Heading/Heading.tsx b/week4/src/components/common/Heading/Heading.tsx new file mode 100644 index 0000000..4a9a082 --- /dev/null +++ b/week4/src/components/common/Heading/Heading.tsx @@ -0,0 +1,31 @@ +import { ComponentPropsWithoutRef } from "react"; + +import { SizeType } from "@/types/size"; + +import { headingStyle } from "./Heading.style"; + +export interface IHeading extends ComponentPropsWithoutRef<"h3"> { + size?: SizeType; +} + +/* SizeType의 union type별 태그 */ +const TAG_BY_SIZE = { + xxLarge: "h1", + xLarge: "h2", + large: "h3", + medium: "h4", + small: "h5", + xSmall: "h6", +}; + +const Heading = ({ size = "large", ...props }: IHeading) => { + const Tag = TAG_BY_SIZE[size] as JSX.ElementType; + + return ( + + {props.children} + + ); +}; + +export default Heading; diff --git a/week4/src/components/common/Img/Img.style.ts b/week4/src/components/common/Img/Img.style.ts new file mode 100644 index 0000000..ecd17be --- /dev/null +++ b/week4/src/components/common/Img/Img.style.ts @@ -0,0 +1,21 @@ +import { css } from "@emotion/react"; +import { ImgProps } from "./Img"; +import { Theme } from "@/styles/theme"; + +export const shapeStyle = (shape: Required["shape"]) => + css({ + borderRadius: shape === "rectangle" ? Theme.borderRadius.medium : "50%", + }); + +export const imgStyle = css({ + objectFit: "cover", +}); + +export const sizeStyle = ( + width: Required["width"], + height: Required["height"] +) => + css({ + width, + height, + }); diff --git a/week4/src/components/common/Img/Img.tsx b/week4/src/components/common/Img/Img.tsx new file mode 100644 index 0000000..20572fe --- /dev/null +++ b/week4/src/components/common/Img/Img.tsx @@ -0,0 +1,27 @@ +import { ImgHTMLAttributes } from "react"; +import { imgStyle, shapeStyle, sizeStyle } from "./Img.style"; + +export interface ImgProps extends ImgHTMLAttributes { + width?: string; + height?: string; + src: string; + shape?: "rectangle" | "circle"; +} + +const Img = ({ + width = "50px", + height = "50px", + src, + shape = "rectangle", + ...props +}: ImgProps) => { + return ( + + ); +}; + +export default Img; diff --git a/week4/src/components/common/Input/Input.style.ts b/week4/src/components/common/Input/Input.style.ts new file mode 100644 index 0000000..3981be5 --- /dev/null +++ b/week4/src/components/common/Input/Input.style.ts @@ -0,0 +1,72 @@ +import { css } from "@emotion/react"; + +import { Theme } from "@styles/theme"; +import { InputProps } from "./Input"; + +export const variantStyle = { + default: css({ + backgroundColor: Theme.color.gray100, + }), + + text: css({ + border: `1px solid ${Theme.color.gray200}`, + backgroundColor: "transparent", + }), +}; + +export const inputWrapperStyle = (isError: Required["isError"]) => + css({ + display: "flex", + gap: "12px", + alignItems: "center", + + paddingTop: 0, + paddingBottom: 0, + borderRadius: Theme.borderRadius.medium, + backgroundColor: Theme.color.gray100, + + transition: "all .2s ease-in", + + boxShadow: isError + ? `inset 0 0 0 1.5px ${Theme.color.red200}` + : `inset 0 0 0 1.5px ${Theme.color.gray300}`, + }); + +export const sizeStyle = { + large: css({ + padding: "12px 16px", + + fontSize: Theme.text.medium.fontSize, + lineHeight: Theme.text.medium.lineHeight, + }), + + medium: css({ + padding: "10px 14px", + + fontSize: Theme.text.medium.fontSize, + lineHeight: Theme.text.medium.lineHeight, + }), + + small: css({ + padding: "8px 12px", + + fontSize: Theme.text.small.fontSize, + lineHeight: Theme.text.small.lineHeight, + }), +}; + +export const inputStyle = css({ + width: "100%", + + padding: "10px 12px", + + border: "none", + borderRadius: Theme.borderRadius.small, + + backgroundColor: "transparent", + + fontSize: Theme.text.medium.fontSize, + lineHeight: Theme.text.medium.lineHeight, + + outline: 0, +}); diff --git a/week4/src/components/common/Input/Input.tsx b/week4/src/components/common/Input/Input.tsx new file mode 100644 index 0000000..ad937b1 --- /dev/null +++ b/week4/src/components/common/Input/Input.tsx @@ -0,0 +1,36 @@ +import { ForwardedRef, InputHTMLAttributes, forwardRef } from "react"; +import Label from "@components/common/Label/Label"; +import SupportingText from "@components/common/SupportingText/SupportingText"; +import { inputStyle, inputWrapperStyle, sizeStyle } from "./Input.style"; +import { SizeType } from "@/types/size"; + +export interface InputProps + extends Omit, "size"> { + label?: string; + size?: Extract; + isError?: boolean; + supportingText?: string; +} + +const Input = ( + { + label, + size = "medium", + isError = false, + supportingText, + ...props + }: InputProps, + ref: ForwardedRef +) => { + return ( +
+ +
+ +
+ {supportingText} +
+ ); +}; + +export default forwardRef(Input); diff --git a/week4/src/components/common/Label/Label.style.ts b/week4/src/components/common/Label/Label.style.ts new file mode 100644 index 0000000..35e57e8 --- /dev/null +++ b/week4/src/components/common/Label/Label.style.ts @@ -0,0 +1,10 @@ +import { css } from "@emotion/react"; + +import { Theme } from "@styles/theme"; + +export const textStyle = css({ + fontSize: Theme.text.medium.fontSize, + lineHeight: Theme.text.medium.lineHeight, + + fontWeight: 600, +}); diff --git a/week4/src/components/common/Label/Label.tsx b/week4/src/components/common/Label/Label.tsx new file mode 100644 index 0000000..ea53388 --- /dev/null +++ b/week4/src/components/common/Label/Label.tsx @@ -0,0 +1,17 @@ +import { LabelHTMLAttributes } from "react"; +import { textStyle } from "./Label.style"; + +interface LabelProps extends LabelHTMLAttributes { + id?: string; + label?: string; +} + +const Label = ({ id, children, ...props }: LabelProps) => { + return ( + + ); +}; + +export default Label; diff --git a/week4/src/components/common/SupportingText/SupportingText.style.ts b/week4/src/components/common/SupportingText/SupportingText.style.ts new file mode 100644 index 0000000..f25a558 --- /dev/null +++ b/week4/src/components/common/SupportingText/SupportingText.style.ts @@ -0,0 +1,18 @@ +import { css } from "@emotion/react"; + +import { Theme } from "@styles/theme"; + +import { SupportingTextProps } from "./SupportingText"; + +export const getTextStyle = ( + isError: Required["isError"] +) => + css({ + fontSize: Theme.text.xSmall.fontSize, + lineHeight: Theme.text.xSmall.lineHeight, + + color: isError ? Theme.color.red300 : Theme.color.gray600, + fontWeight: 600, + + minHeight: Theme.text.xSmall.lineHeight, + }); diff --git a/week4/src/components/common/SupportingText/SupportingText.tsx b/week4/src/components/common/SupportingText/SupportingText.tsx new file mode 100644 index 0000000..167417a --- /dev/null +++ b/week4/src/components/common/SupportingText/SupportingText.tsx @@ -0,0 +1,12 @@ +import { getTextStyle } from "./SupportingText.style"; + +export interface SupportingTextProps + extends React.HTMLAttributes { + isError?: boolean; +} + +const SupportingText = ({ isError = false, children }: SupportingTextProps) => { + return

{children}

; +}; + +export default SupportingText; diff --git a/week4/src/components/common/Text/Text.style.ts b/week4/src/components/common/Text/Text.style.ts new file mode 100644 index 0000000..fe506dd --- /dev/null +++ b/week4/src/components/common/Text/Text.style.ts @@ -0,0 +1,25 @@ +import { css } from "@emotion/react"; + +import { Theme } from "@styles/theme"; + +export const textStyle = { + large: css({ + fontSize: Theme.text.large.fontSize, + lineHeight: Theme.text.large.lineHeight, + }), + + medium: css({ + fontSize: Theme.text.medium.fontSize, + lineHeight: Theme.text.medium.lineHeight, + }), + + small: css({ + fontSize: Theme.text.small.fontSize, + lineHeight: Theme.text.small.lineHeight, + }), + + xSmall: css({ + fontSize: Theme.text.xSmall.fontSize, + lineHeight: Theme.text.xSmall.lineHeight, + }), +}; diff --git a/week4/src/components/common/Text/Text.tsx b/week4/src/components/common/Text/Text.tsx new file mode 100644 index 0000000..796c35e --- /dev/null +++ b/week4/src/components/common/Text/Text.tsx @@ -0,0 +1,20 @@ +import { ComponentPropsWithoutRef, ReactNode } from "react"; + +import { SizeType } from "@/types/size"; + +import { textStyle } from "./Text.style"; + +export interface IText extends ComponentPropsWithoutRef<"p"> { + size: Extract; + children: ReactNode; +} + +const Text = ({ size = "medium", children, ...props }: IText) => { + return ( +

+ {children} +

+ ); +}; + +export default Text; diff --git a/week4/src/components/common/Video/Video.tsx b/week4/src/components/common/Video/Video.tsx new file mode 100644 index 0000000..7538d1f --- /dev/null +++ b/week4/src/components/common/Video/Video.tsx @@ -0,0 +1,26 @@ +import { ComponentPropsWithRef, ForwardedRef, forwardRef } from "react"; + +interface VideoProps extends ComponentPropsWithRef<"video"> { + width?: string; + src?: string; + autoplay?: boolean; + controls?: boolean; +} + +const Video = ( + { width, src, autoplay, controls, ...props }: VideoProps, + ref: ForwardedRef +) => { + return ( +