From e04eac569d530ab0e14dfb45fa0a4de9d02b6923 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 18:59:09 +0900 Subject: [PATCH 01/61] =?UTF-8?q?feat(DefaultButton):=20onClick=20?= =?UTF-8?q?=EC=86=8D=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Common Components 개발 #8 --- Components/Common/DefaultButton.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Components/Common/DefaultButton.tsx b/Components/Common/DefaultButton.tsx index cf06ea8d..58a61d3b 100644 --- a/Components/Common/DefaultButton.tsx +++ b/Components/Common/DefaultButton.tsx @@ -1,5 +1,6 @@ //todo! line57 : as any를 지우고 overload 문제 해결해야 합니다. +import { MouseEventHandler } from "react"; import styled from "styled-components"; type DefaultButtonType = "full" | "outline"; @@ -9,6 +10,7 @@ interface DefaultButtonProps { text: string; type: DefaultButtonType; size: DefaultButtonSize; + onClick: MouseEventHandler; } const getDefaultButtonType = (type: DefaultButtonType) => { @@ -32,9 +34,9 @@ const getDefaultButtonSize = (size: DefaultButtonSize) => { height: 2.5rem;`; }; -const DefaultButton = ({ text, type, size }: DefaultButtonProps) => { +const DefaultButton = ({ text, type, size, onClick }: DefaultButtonProps) => { return ( - + {text} ); From 8ed1dc229afb53c68523b00d973787c035506765 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 19:01:36 +0900 Subject: [PATCH 02/61] =?UTF-8?q?feat(Banner):=20Banner=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/MyPage/Banner.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Components/MyPage/Banner.tsx diff --git a/Components/MyPage/Banner.tsx b/Components/MyPage/Banner.tsx new file mode 100644 index 00000000..2abcc04e --- /dev/null +++ b/Components/MyPage/Banner.tsx @@ -0,0 +1,9 @@ +import styled from "styled-components"; + +const Banner = styled.div` + width: 100vw; + height: 180px; + background-color: grey; +`; + +export default Banner; From 7bf280ac3bfe6a95693e45093f58dd3f6f313f58 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 22:41:09 +0900 Subject: [PATCH 03/61] =?UTF-8?q?fix:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/MyPage/Banner.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Components/MyPage/Banner.tsx b/Components/MyPage/Banner.tsx index 2abcc04e..65692bdd 100644 --- a/Components/MyPage/Banner.tsx +++ b/Components/MyPage/Banner.tsx @@ -2,7 +2,7 @@ import styled from "styled-components"; const Banner = styled.div` width: 100vw; - height: 180px; + height: 11.25rem; background-color: grey; `; From 952d3161dfbcf2db0c41868c2f6331e2fb284443 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 20:13:23 +0900 Subject: [PATCH 04/61] =?UTF-8?q?feat(Tabs):=20Tabs=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/MyPage/Tabs.tsx | 46 ++++++++++++++++++++++++++++++++++++++ pages/index.tsx | 2 ++ 2 files changed, 48 insertions(+) create mode 100644 Components/MyPage/Tabs.tsx diff --git a/Components/MyPage/Tabs.tsx b/Components/MyPage/Tabs.tsx new file mode 100644 index 00000000..431e8089 --- /dev/null +++ b/Components/MyPage/Tabs.tsx @@ -0,0 +1,46 @@ +import { useState } from "react"; +import styled from "styled-components"; + +const Tabs = () => { + const tabList = [ + "프로젝트", + "팔로잉", + "북마크", + "좋아요", + "보관함", + "프로필", + ]; + const [currentTab, setCurrentTab] = useState(1); + return ( + + {tabList.map((tab, idx) => ( + setCurrentTab(idx)} + > + {tab} + + ))} + + ); +}; + +const TabsContainer = styled.div` + display: flex; + flex-direction: row; +`; + +interface TabWrapperProps { + active: boolean; +} + +const TabWrapper = styled.div` + width: 68px; + text-align: center; + padding: 16px; + border-bottom: 2px solid ${({ active }) => (active ? "black" : "grey")}; + cursor: pointer; +`; + +export default Tabs; diff --git a/pages/index.tsx b/pages/index.tsx index 9b0ae03e..3a81fbc6 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,3 +1,4 @@ +import Tabs from "@/Components/MyPage/Tabs"; import Head from "next/head"; const Home = () => { @@ -10,6 +11,7 @@ const Home = () => {
start
+ ); }; From 4027d231fb6ce97500a5cbc41a9af3d8cb965320 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 20:35:46 +0900 Subject: [PATCH 05/61] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index 3a81fbc6..9b0ae03e 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,4 +1,3 @@ -import Tabs from "@/Components/MyPage/Tabs"; import Head from "next/head"; const Home = () => { @@ -11,7 +10,6 @@ const Home = () => {
start
- ); }; From bc37ce1b7d2a529b583e346001a416943e590493 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 22:44:47 +0900 Subject: [PATCH 06/61] =?UTF-8?q?fix:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/MyPage/Tabs.tsx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Components/MyPage/Tabs.tsx b/Components/MyPage/Tabs.tsx index 431e8089..b937fa63 100644 --- a/Components/MyPage/Tabs.tsx +++ b/Components/MyPage/Tabs.tsx @@ -1,16 +1,10 @@ import { useState } from "react"; import styled from "styled-components"; +const tabList = ["프로젝트", "팔로잉", "북마크", "좋아요", "보관함", "프로필"]; + const Tabs = () => { - const tabList = [ - "프로젝트", - "팔로잉", - "북마크", - "좋아요", - "보관함", - "프로필", - ]; - const [currentTab, setCurrentTab] = useState(1); + const [currentTab, setCurrentTab] = useState(0); return ( {tabList.map((tab, idx) => ( @@ -36,10 +30,10 @@ interface TabWrapperProps { } const TabWrapper = styled.div` - width: 68px; + width: 4.25rem; text-align: center; - padding: 16px; - border-bottom: 2px solid ${({ active }) => (active ? "black" : "grey")}; + padding: 1rem; + border-bottom: 0.125rem solid ${({ active }) => (active ? "black" : "grey")}; cursor: pointer; `; From eaa2677eaf9524403456a0b18adbaf03b93cd0d5 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 20:35:03 +0900 Subject: [PATCH 07/61] =?UTF-8?q?feat(SwitchButton):=20MyPage=EC=9D=98=20S?= =?UTF-8?q?witchButton=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=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 --- Components/MyPage/SwitchButton.tsx | 67 ++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Components/MyPage/SwitchButton.tsx diff --git a/Components/MyPage/SwitchButton.tsx b/Components/MyPage/SwitchButton.tsx new file mode 100644 index 00000000..e243fe41 --- /dev/null +++ b/Components/MyPage/SwitchButton.tsx @@ -0,0 +1,67 @@ +import styled from "styled-components"; + +type CurrentItemType = "남성" | "여성" | "선택 안함"; + +interface SwitchButtonProps { + currentItem: string; + setCurrentItem: (currentItem: CurrentItemType) => void; +} + +const SwitchButton = ({ currentItem, setCurrentItem }: SwitchButtonProps) => { + return ( + + setCurrentItem("남성")} + > + 남성 + + setCurrentItem("여성")} + > + 여성 + + setCurrentItem("선택 안함")} + > + 선택 안함 + + + ); +}; + +const SwitchButtonContainer = styled.div` + display: flex; + flex-direction: row; + + filter: drop-shadow(2px 4px 12px rgba(0, 0, 0, 0.1)) + drop-shadow(0px 0px 4px rgba(0, 0, 0, 0.1)); +`; + +interface DefaultButtonProps { + active: boolean; +} + +const DefaultButton = styled.button` + border: none; + cursor: pointer; + width: 100px; + height: 44px; + font-size: 16px; + color: ${({ active }) => (active ? "white" : "black")}; + background-color: ${({ active }) => (active ? "black" : "white")}; +`; + +const HeadButton = styled(DefaultButton)` + border-top-left-radius: 12px; + border-bottom-left-radius: 12px; +`; + +const TailButton = styled(DefaultButton)` + border-top-right-radius: 12px; + border-bottom-right-radius: 12px; +`; + +export default SwitchButton; From f97e6656080848cf4567c61ec4f7caf3523efc3f Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 22:40:11 +0900 Subject: [PATCH 08/61] =?UTF-8?q?fix:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/MyPage/SwitchButton.tsx | 60 ++++++++++++------------------ 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/Components/MyPage/SwitchButton.tsx b/Components/MyPage/SwitchButton.tsx index e243fe41..2712f476 100644 --- a/Components/MyPage/SwitchButton.tsx +++ b/Components/MyPage/SwitchButton.tsx @@ -1,33 +1,23 @@ import styled from "styled-components"; -type CurrentItemType = "남성" | "여성" | "선택 안함"; - interface SwitchButtonProps { currentItem: string; - setCurrentItem: (currentItem: CurrentItemType) => void; + setCurrentItem: (currentItem: string) => void; } const SwitchButton = ({ currentItem, setCurrentItem }: SwitchButtonProps) => { + const items = ["남성", "여성", "선택 안함"]; return ( - setCurrentItem("남성")} - > - 남성 - - setCurrentItem("여성")} - > - 여성 - - setCurrentItem("선택 안함")} - > - 선택 안함 - + {items.map((item) => ( + setCurrentItem(item)} + > + {item} + + ))} ); }; @@ -36,8 +26,8 @@ const SwitchButtonContainer = styled.div` display: flex; flex-direction: row; - filter: drop-shadow(2px 4px 12px rgba(0, 0, 0, 0.1)) - drop-shadow(0px 0px 4px rgba(0, 0, 0, 0.1)); + filter: drop-shadow(0.125rem 0.25rem 0.75rem rgba(0, 0, 0, 0.1)) + drop-shadow(0rem 0rem 0.25rem rgba(0, 0, 0, 0.1)); `; interface DefaultButtonProps { @@ -47,21 +37,19 @@ interface DefaultButtonProps { const DefaultButton = styled.button` border: none; cursor: pointer; - width: 100px; - height: 44px; - font-size: 16px; + width: 6.25rem; + height: 2.75rem; + font-size: 1rem; color: ${({ active }) => (active ? "white" : "black")}; background-color: ${({ active }) => (active ? "black" : "white")}; -`; - -const HeadButton = styled(DefaultButton)` - border-top-left-radius: 12px; - border-bottom-left-radius: 12px; -`; - -const TailButton = styled(DefaultButton)` - border-top-right-radius: 12px; - border-bottom-right-radius: 12px; + :first-child { + border-top-left-radius: 0.75rem; + border-bottom-left-radius: 0.75rem; + } + :last-child { + border-top-right-radius: 0.75rem; + border-bottom-right-radius: 0.75rem; + } `; export default SwitchButton; From 8d53ebac7aa10b38cdb84d10b78373ec19392af9 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 20:53:14 +0900 Subject: [PATCH 09/61] =?UTF-8?q?feat(PositionTag):=20MyPage=EC=9D=98=20Po?= =?UTF-8?q?sitionTag=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=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 --- Components/MyPage/PositionTag.tsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Components/MyPage/PositionTag.tsx diff --git a/Components/MyPage/PositionTag.tsx b/Components/MyPage/PositionTag.tsx new file mode 100644 index 00000000..77d5f79e --- /dev/null +++ b/Components/MyPage/PositionTag.tsx @@ -0,0 +1,17 @@ +import styled from "styled-components"; + +interface PositionTagProps { + active: boolean; +} + +const PositionTag = styled.button` + height: 34px; + padding: 0 16px; + border-radius: 50px; + cursor: pointer; + color: ${({ active }) => (active ? "white" : "#999999")}; + border: 1px solid ${({ active }) => (active ? "transparent" : "#999999")}; + background-color: ${({ active }) => (active ? "#999999" : "white")}; +`; + +export default PositionTag; From 7229c1c9ca8d0807f396276a0fe1b4bee48df651 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 22:46:01 +0900 Subject: [PATCH 10/61] =?UTF-8?q?fix:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/MyPage/PositionTag.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Components/MyPage/PositionTag.tsx b/Components/MyPage/PositionTag.tsx index 77d5f79e..fbd67601 100644 --- a/Components/MyPage/PositionTag.tsx +++ b/Components/MyPage/PositionTag.tsx @@ -5,12 +5,13 @@ interface PositionTagProps { } const PositionTag = styled.button` - height: 34px; - padding: 0 16px; - border-radius: 50px; + height: 2.125rem; + padding: 0 1rem; + border-radius: 3.125rem; cursor: pointer; color: ${({ active }) => (active ? "white" : "#999999")}; - border: 1px solid ${({ active }) => (active ? "transparent" : "#999999")}; + border: 0.0625rem solid + ${({ active }) => (active ? "transparent" : "#999999")}; background-color: ${({ active }) => (active ? "#999999" : "white")}; `; From 9e7dcb02c200699dd28f6899bffe34fc4491df7c Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 20:41:03 +0900 Subject: [PATCH 11/61] =?UTF-8?q?feat(ProfileContainer):=20MyPage=EC=9D=98?= =?UTF-8?q?=20ProfileContainer=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 --- Components/MyPage/ProfileContainer.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Components/MyPage/ProfileContainer.tsx diff --git a/Components/MyPage/ProfileContainer.tsx b/Components/MyPage/ProfileContainer.tsx new file mode 100644 index 00000000..35048292 --- /dev/null +++ b/Components/MyPage/ProfileContainer.tsx @@ -0,0 +1,10 @@ +import styled from "styled-components"; + +const ProfileContainer = styled.div` + padding: 52px; + background-color: #f2f2f2; + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + border-radius: 8px; +`; + +export default ProfileContainer; From f70192eaedf6e4b2bb84dd9b917d07c02e1195a1 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Fri, 10 Feb 2023 22:46:41 +0900 Subject: [PATCH 12/61] =?UTF-8?q?fix:=20=ED=94=BC=EB=93=9C=EB=B0=B1=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/MyPage/ProfileContainer.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Components/MyPage/ProfileContainer.tsx b/Components/MyPage/ProfileContainer.tsx index 35048292..c0832a14 100644 --- a/Components/MyPage/ProfileContainer.tsx +++ b/Components/MyPage/ProfileContainer.tsx @@ -1,10 +1,10 @@ import styled from "styled-components"; const ProfileContainer = styled.div` - padding: 52px; + padding: 3.25rem; background-color: #f2f2f2; - box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); - border-radius: 8px; + box-shadow: 0rem 0.25rem 0.25rem rgba(0, 0, 0, 0.25); + border-radius: 0.5rem; `; export default ProfileContainer; From d458229957704a8285efc7684539b026566a24ab Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Fri, 10 Feb 2023 16:12:13 +0900 Subject: [PATCH 13/61] =?UTF-8?q?feat:=20Tags=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20UI=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tags 컴포넌트 로직 없이 UI만 생성합니다. tags는 개별 tag의 묶음입니다. #8 --- Components/Common/Tags.tsx | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Components/Common/Tags.tsx diff --git a/Components/Common/Tags.tsx b/Components/Common/Tags.tsx new file mode 100644 index 00000000..444df53a --- /dev/null +++ b/Components/Common/Tags.tsx @@ -0,0 +1,44 @@ +import styled from "styled-components"; + +/** + * @TODO Set 자료형으로 리팩토링하기. 중복을 막아야 합니다. + * Set에는 순회하는 메서드를 찾아야 합니다. + * 메서드 찾아주시면 PR에 추가 커밋으로 반영하겠습니다. + */ + +interface TagsProps { + TagsItems: string[]; +} + +/** + * 문자열만 들어간 Array만 Props로 받습니다. + * li태그를 styled 컴포넌트로 활용하지 않은 이유는 key가 없기 때문입니다. + */ +const Tags = ({ TagsItems }: TagsProps) => { + return ( + + {TagsItems.map((item) => ( + {item} + ))} + + ); +}; + +const TagsContainer = styled.ul` + display: flex; + gap: 0.25rem; +`; + +type TagsItemType = { + key: string; +}; + +const TagsItem = styled.li` + background-color: #999999; + color: #f2f2f2; + font-size: 0.75rem; + padding: 0 0.5rem 0.25rem; + border-radius: 0.75rem; +`; + +export default Tags; From 9498b966d8333762fb08bcb523cb335f7100840d Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Fri, 10 Feb 2023 17:25:07 +0900 Subject: [PATCH 14/61] =?UTF-8?q?refactor:=20Tags.tsx=20Props=20type=20?= =?UTF-8?q?=EC=8B=9D=EB=B3=84=EC=9E=90=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - TagsItems를 tagItems로 복수형의 복수형을 단수형의 복수형으로 수정합니다. - 복수의 목록이 아닌 단일 목록이기 때문에 변경합니다. - 파스칼 케이스를 케멀케이스로 수정합니다. #8 --- Components/Common/Tags.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Components/Common/Tags.tsx b/Components/Common/Tags.tsx index 444df53a..e0a866a4 100644 --- a/Components/Common/Tags.tsx +++ b/Components/Common/Tags.tsx @@ -2,22 +2,26 @@ import styled from "styled-components"; /** * @TODO Set 자료형으로 리팩토링하기. 중복을 막아야 합니다. - * Set에는 순회하는 메서드를 찾아야 합니다. - * 메서드 찾아주시면 PR에 추가 커밋으로 반영하겠습니다. + * 1. Set에는 순회하는 메서드를 찾아야 합니다. + * 2. 메서드 찾아주시면 PR에 추가 커밋으로 반영하겠습니다. + * + * @TODO size: "sm" | "lg" | "md"; 추가하기 + * 동작하는 로직을 추가할 때는 여기로 추가합니다. + * 아이콘 클릭에 삭제, 태그 클릭에 추가... */ interface TagsProps { - TagsItems: string[]; + tagItems: string[]; } /** * 문자열만 들어간 Array만 Props로 받습니다. * li태그를 styled 컴포넌트로 활용하지 않은 이유는 key가 없기 때문입니다. */ -const Tags = ({ TagsItems }: TagsProps) => { +const Tags = ({ tagItems }: TagsProps) => { return ( - {TagsItems.map((item) => ( + {tagItems.map((item) => ( {item} ))} From 95cb625680c9a8dd8acdafcf0acae4167558c88d Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Fri, 10 Feb 2023 19:00:52 +0900 Subject: [PATCH 15/61] =?UTF-8?q?feat:=20Card.tsx,=20IconCount.tsx:=20=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B5=9C=EC=B4=88?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 큰틀에서 Card 컴포넌트를 구현합니다. #8 --- Components/Common/Card/Card.tsx | 100 +++++++++++++++++++++++++++ Components/Common/Card/IconCount.tsx | 25 +++++++ 2 files changed, 125 insertions(+) create mode 100644 Components/Common/Card/Card.tsx create mode 100644 Components/Common/Card/IconCount.tsx diff --git a/Components/Common/Card/Card.tsx b/Components/Common/Card/Card.tsx new file mode 100644 index 00000000..bc71f807 --- /dev/null +++ b/Components/Common/Card/Card.tsx @@ -0,0 +1,100 @@ +import Image from "next/image"; +import styled from "styled-components"; +import Tags from "../Tags"; +import IconCount from "./IconCount"; + +/** + * 여기는 CardItem에 해당하는 컴포넌트입니다. + * @TODO comment icon이 나오면 props를 수정합니다. + * @TODO post에서 pick and omit로 타입 조합하기 + */ + +interface CardProps { + src: string; + alt: string; + tagItems: string[]; + title: string; + subTitle: string; + date: string; + likes: number; + comments: number; +} + +const Card = ({ + tagItems, + src, + alt, + title, + subTitle, + date, + likes, + comments, +}: CardProps) => { + return ( + + + {alt} + + + {date} + + + + + + {title} + {subTitle} + + + ); +}; + +const CardContainer = styled.div` + width: 18.75rem; + height: 19.125rem; +`; + +const ImageContainer = styled.div` + width: 18.75rem; + height: 11.25rem; + object-fit: cover; + position: relative; +`; + +const Title = styled.h2` + font-size: 1rem; + font-weight: 500; +`; + +const SubTitle = styled.h3` + //styleName: Body/Body-13; + font-size: 0.8125rem; + font-weight: 400; + text-align: left; + color: #b3b3b3; +`; + +const DateCountContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + color: #b3b3b3; +`; + +const Date = styled.div` + font-weight: 400; + font-size: 12px; +`; + +const IconCountContainer = styled.div` + display: flex; +`; + +export default Card; diff --git a/Components/Common/Card/IconCount.tsx b/Components/Common/Card/IconCount.tsx new file mode 100644 index 00000000..28c1c9d3 --- /dev/null +++ b/Components/Common/Card/IconCount.tsx @@ -0,0 +1,25 @@ +import Image from "next/image"; +import styled from "styled-components"; + +interface IconCountProps { + icon: string; + count: number; +} + +const IconCount = ({ icon, count }: IconCountProps) => { + return ( + + {icon} +
{count}
+
+ ); +}; + +const IconCountContainer = styled.div` + display: flex; + flex-direction: row; + align-items: center; + gap: 0; +`; + +export default IconCount; From e7ed400f9300b56c90f4d29a5aaec26cb03b9939 Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Fri, 10 Feb 2023 21:49:40 +0900 Subject: [PATCH 16/61] =?UTF-8?q?refactor(CardItem,=20Tags,=20IconCount):?= =?UTF-8?q?=20=EC=A4=91=EC=95=99=EC=A0=95=EB=A0=AC,=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 모듈명 Card에서 CardItem으로 변경 - 스타일링 정렬합니다. - 사용예시를 문서화합니다. - Tags를 수정합니다. - 가운데 정렬합니다. - 많아지면 줄바꿈 처리합니다. - tags를 추가 작업을 문서화합니다. - IconCount 컴포넌트 텍스트를 중앙정렬합니다. #8 --- Components/Common/Card/Card.tsx | 100 --------------- Components/Common/Card/CardItem.tsx | 174 +++++++++++++++++++++++++++ Components/Common/Card/IconCount.tsx | 1 + Components/Common/Tags.tsx | 6 +- 4 files changed, 180 insertions(+), 101 deletions(-) delete mode 100644 Components/Common/Card/Card.tsx create mode 100644 Components/Common/Card/CardItem.tsx diff --git a/Components/Common/Card/Card.tsx b/Components/Common/Card/Card.tsx deleted file mode 100644 index bc71f807..00000000 --- a/Components/Common/Card/Card.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import Image from "next/image"; -import styled from "styled-components"; -import Tags from "../Tags"; -import IconCount from "./IconCount"; - -/** - * 여기는 CardItem에 해당하는 컴포넌트입니다. - * @TODO comment icon이 나오면 props를 수정합니다. - * @TODO post에서 pick and omit로 타입 조합하기 - */ - -interface CardProps { - src: string; - alt: string; - tagItems: string[]; - title: string; - subTitle: string; - date: string; - likes: number; - comments: number; -} - -const Card = ({ - tagItems, - src, - alt, - title, - subTitle, - date, - likes, - comments, -}: CardProps) => { - return ( - - - {alt} - - - {date} - - - - - - {title} - {subTitle} - - - ); -}; - -const CardContainer = styled.div` - width: 18.75rem; - height: 19.125rem; -`; - -const ImageContainer = styled.div` - width: 18.75rem; - height: 11.25rem; - object-fit: cover; - position: relative; -`; - -const Title = styled.h2` - font-size: 1rem; - font-weight: 500; -`; - -const SubTitle = styled.h3` - //styleName: Body/Body-13; - font-size: 0.8125rem; - font-weight: 400; - text-align: left; - color: #b3b3b3; -`; - -const DateCountContainer = styled.div` - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - color: #b3b3b3; -`; - -const Date = styled.div` - font-weight: 400; - font-size: 12px; -`; - -const IconCountContainer = styled.div` - display: flex; -`; - -export default Card; diff --git a/Components/Common/Card/CardItem.tsx b/Components/Common/Card/CardItem.tsx new file mode 100644 index 00000000..5e868c1b --- /dev/null +++ b/Components/Common/Card/CardItem.tsx @@ -0,0 +1,174 @@ +import Image from "next/image"; +import Link from "next/link"; +import styled from "styled-components"; +import Tags from "../Tags"; +import IconCount from "./IconCount"; + +/** + * 여기는 CardItem에 해당하는 컴포넌트입니다. + * @TODO comment icon이 추가로 나오면 IconCount에 대입하는 props를 수정합니다. + * @TODO post에서 pick and omit로 타입 조합하기 + * @TODO Image Hover에 작성자 프로필 보여주기 + */ + +type Field = + | "WEB" + | "APP" + | "SOFTWARE" + | "DATA" + | "WEB3" + | "DEVOPS" + | "IOT_AND_EMBEDDED" + | "SECURITY"; + +interface CardProps { + imageSrc: string; + imageAlt: string; + linkURL: string; + tagItems: string[]; + title: string; + subTitle: string; + date: string; + likes: number; + comments: number; + field: Field; +} + +/** + * @param {string} imageSrc - 이미지 url가 보이는 url + * @param {string} imageAlt - 이미지 alt 텍스트 + * @param {string} linkURL - 클릭하면 연결 Detail 페이지로 이동합니다. + * @param {string[]} tagItems - 태그 목록 + * @param {string} title - 게시글 제목 + * @param {string} subTitle - 게시글 설명 + * @param {string} date - 게시글 게시일 + * @param {string} likes - 좋아요 수 + * @param {string} comments - 댓글 수 + * @param {string} filed - 분야 + * @constructor + * @example + * + */ + +const Card = ({ + tagItems, + imageSrc, + linkURL, + imageAlt, + title, + subTitle, + date, + likes, + comments, + field, +}: CardProps) => { + return ( + + + + + {imageAlt} + + + + + {date} + + + + + + + {title} + {subTitle} + + + + + ); +}; + +const CardContainer = styled.div` + width: 18.75rem; +`; + +const ImageContainer = styled.div` + width: 18.75rem; + height: 11.25rem; + position: relative; + margin: 0 0 0.75rem 0; + cursor: pointer; + + ul { + position: absolute; + top: 0.5rem; + left: 0.5rem; + z-index: 1; + } + + img { + object-fit: cover; + border-radius: 0.5rem; + } +`; + +const CardBottomWrapper = styled.div` + padding: 0 0.5rem 0.5rem; + display: flex; + flex-direction: column; + gap: 0.75rem; +`; + +const TitleWrapper = styled.div` + display: flex; + flex-direction: column; + gap: 0.5rem; +`; + +const Title = styled.h2` + font-size: 1rem; + font-weight: 500; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +`; + +const SubTitle = styled.h3` + font-size: 0.8125rem; + font-weight: 400; + text-align: left; + color: #b3b3b3; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +`; + +const DateCountContainer = styled.div` + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + color: #b3b3b3; +`; + +const Date = styled.div` + font-weight: 400; + font-size: 0.75rem; +`; + +const IconCountContainer = styled.div` + display: flex; +`; + +export default Card; diff --git a/Components/Common/Card/IconCount.tsx b/Components/Common/Card/IconCount.tsx index 28c1c9d3..f7e4d025 100644 --- a/Components/Common/Card/IconCount.tsx +++ b/Components/Common/Card/IconCount.tsx @@ -19,6 +19,7 @@ const IconCountContainer = styled.div` display: flex; flex-direction: row; align-items: center; + font-size: 0.75rem; gap: 0; `; diff --git a/Components/Common/Tags.tsx b/Components/Common/Tags.tsx index e0a866a4..80f838fd 100644 --- a/Components/Common/Tags.tsx +++ b/Components/Common/Tags.tsx @@ -8,6 +8,8 @@ import styled from "styled-components"; * @TODO size: "sm" | "lg" | "md"; 추가하기 * 동작하는 로직을 추가할 때는 여기로 추가합니다. * 아이콘 클릭에 삭제, 태그 클릭에 추가... + * + * @TODO 태그 길이 초과하면 줄바꿈 처리 안 하고 (...) 표시하기 */ interface TagsProps { @@ -31,6 +33,8 @@ const Tags = ({ tagItems }: TagsProps) => { const TagsContainer = styled.ul` display: flex; gap: 0.25rem; + /* 태그를 많이 넣었을 때 줄바꿈 처리합니다. */ + flex-wrap: wrap; `; type TagsItemType = { @@ -41,7 +45,7 @@ const TagsItem = styled.li` background-color: #999999; color: #f2f2f2; font-size: 0.75rem; - padding: 0 0.5rem 0.25rem; + padding: 0.25rem 0.5rem; border-radius: 0.75rem; `; From a9caa44191d3d2ffb4581c46ea96a329b831696a Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Fri, 10 Feb 2023 23:13:39 +0900 Subject: [PATCH 17/61] =?UTF-8?q?refactor=20(IconWithCount,=20Tags):=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=EB=AA=85=20=EC=88=98=EC=A0=95,=20Tag=20?= =?UTF-8?q?=EC=A4=84=EB=B0=94=EA=BF=88=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 모듈명 IconCount를 IconWithCount로 변경합니다. - tags 줄바꿈 대신에 여러 태그에 (...)으로 변경합니다. #8 --- Components/Common/Card/CardItem.tsx | 8 +++++--- .../Common/Card/{IconCount.tsx => IconWithCount.tsx} | 4 ++-- Components/Common/Tags.tsx | 10 +++++++--- 3 files changed, 14 insertions(+), 8 deletions(-) rename Components/Common/Card/{IconCount.tsx => IconWithCount.tsx} (83%) diff --git a/Components/Common/Card/CardItem.tsx b/Components/Common/Card/CardItem.tsx index 5e868c1b..72b4d800 100644 --- a/Components/Common/Card/CardItem.tsx +++ b/Components/Common/Card/CardItem.tsx @@ -1,8 +1,9 @@ import Image from "next/image"; import Link from "next/link"; import styled from "styled-components"; +import ProfileImage from "../ProfileImage"; import Tags from "../Tags"; -import IconCount from "./IconCount"; +import IconWithCount from "./IconWithCount"; /** * 여기는 CardItem에 해당하는 컴포넌트입니다. @@ -79,14 +80,15 @@ const Card = ({ {imageAlt} + {date} - - + + diff --git a/Components/Common/Card/IconCount.tsx b/Components/Common/Card/IconWithCount.tsx similarity index 83% rename from Components/Common/Card/IconCount.tsx rename to Components/Common/Card/IconWithCount.tsx index f7e4d025..5e0e4616 100644 --- a/Components/Common/Card/IconCount.tsx +++ b/Components/Common/Card/IconWithCount.tsx @@ -6,7 +6,7 @@ interface IconCountProps { count: number; } -const IconCount = ({ icon, count }: IconCountProps) => { +const IconWithCount = ({ icon, count }: IconCountProps) => { return ( {icon} @@ -23,4 +23,4 @@ const IconCountContainer = styled.div` gap: 0; `; -export default IconCount; +export default IconWithCount; diff --git a/Components/Common/Tags.tsx b/Components/Common/Tags.tsx index 80f838fd..ad6171f4 100644 --- a/Components/Common/Tags.tsx +++ b/Components/Common/Tags.tsx @@ -9,7 +9,10 @@ import styled from "styled-components"; * 동작하는 로직을 추가할 때는 여기로 추가합니다. * 아이콘 클릭에 삭제, 태그 클릭에 추가... * - * @TODO 태그 길이 초과하면 줄바꿈 처리 안 하고 (...) 표시하기 + * @TODO 태그 길이 초과하면 줄바꿈 처리 안 하고 보이는 마지막 태그만(...) 표시하기 + * 현재는 아래와 같은 문제가 있습니다. + * Components API TDD 애자일 익스트림 프로그래밍 + * Compo... A... T... 애... 익스트림 프... */ interface TagsProps { @@ -33,8 +36,6 @@ const Tags = ({ tagItems }: TagsProps) => { const TagsContainer = styled.ul` display: flex; gap: 0.25rem; - /* 태그를 많이 넣었을 때 줄바꿈 처리합니다. */ - flex-wrap: wrap; `; type TagsItemType = { @@ -47,6 +48,9 @@ const TagsItem = styled.li` font-size: 0.75rem; padding: 0.25rem 0.5rem; border-radius: 0.75rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; `; export default Tags; From f3ec1d2c66c81d5eebd64bcbaa1b88510e3a18a2 Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Sat, 11 Feb 2023 00:32:44 +0900 Subject: [PATCH 18/61] =?UTF-8?q?feat=20(ico-hart.svg):=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ico-heart 아이콘을 추가합니다. #8 --- public/icons/ico-heart.svg | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 public/icons/ico-heart.svg diff --git a/public/icons/ico-heart.svg b/public/icons/ico-heart.svg new file mode 100644 index 00000000..a2f2b1a5 --- /dev/null +++ b/public/icons/ico-heart.svg @@ -0,0 +1,3 @@ + + + From c52786b8817c7ed132e5bcb8ef1c499f3883772c Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Sat, 11 Feb 2023 00:54:23 +0900 Subject: [PATCH 19/61] =?UTF-8?q?docs=20(CardItem,=20Tags):=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=EB=AA=85=EA=B3=BC=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=9D=B4=EB=A6=84=20=ED=86=B5=EC=9D=BC=20Tag=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Tag 추가 문서화 - 줄바꿈 문제 가로스크롤 지원 여부 선택지로 추가 문서화 - 컴포넌트명 모듈명과 통일 #8 --- Components/Common/Card/CardItem.tsx | 4 ++-- Components/Common/Tags.tsx | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Components/Common/Card/CardItem.tsx b/Components/Common/Card/CardItem.tsx index 72b4d800..fc95468e 100644 --- a/Components/Common/Card/CardItem.tsx +++ b/Components/Common/Card/CardItem.tsx @@ -62,7 +62,7 @@ interface CardProps { * /> */ -const Card = ({ +const CardItem = ({ tagItems, imageSrc, linkURL, @@ -173,4 +173,4 @@ const IconCountContainer = styled.div` display: flex; `; -export default Card; +export default CardItem; diff --git a/Components/Common/Tags.tsx b/Components/Common/Tags.tsx index ad6171f4..70fbbc3c 100644 --- a/Components/Common/Tags.tsx +++ b/Components/Common/Tags.tsx @@ -13,6 +13,7 @@ import styled from "styled-components"; * 현재는 아래와 같은 문제가 있습니다. * Components API TDD 애자일 익스트림 프로그래밍 * Compo... A... T... 애... 익스트림 프... + * 가로 스크롤로 처리하는 방안도 있습니다. */ interface TagsProps { From aa2839f983384bcbd908c3a88f7a1bbf680e7d2f Mon Sep 17 00:00:00 2001 From: hyoloui Date: Fri, 10 Feb 2023 16:30:42 +0900 Subject: [PATCH 20/61] =?UTF-8?q?chore:=20toast=20ui=20Add=20dependencieds?= =?UTF-8?q?=20-=20=ED=86=A0=EC=8A=A4=ED=8A=B8=20ui=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC?= =?UTF-8?q?=EB=A6=AC=20=EC=84=A4=EC=B9=98=ED=95=98=EC=98=80=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.(=EB=94=94=ED=8E=9C=EB=8D=98=EC=8B=9C)=20#8?= =?UTF-8?q?=20@by=20hyoloui?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/package.json b/package.json index 262af290..942fb347 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "typescript": "4.9.5" }, "devDependencies": { + "@toast-ui/select-box": "^1.1.0", "@types/lodash": "^4.14.191", "@types/node": "18.13.0", "@types/react": "18.0.27", diff --git a/yarn.lock b/yarn.lock index c0bc7238..74464155 100644 --- a/yarn.lock +++ b/yarn.lock @@ -430,6 +430,11 @@ dependencies: "@toast-ui/editor" "^3.2.1" +"@toast-ui/select-box@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@toast-ui/select-box/-/select-box-1.1.0.tgz#eee7859054b192cbdce3c661de33e2b0be3bd343" + integrity sha512-arLYZ0xN2cmrvyB84SIS2NDkNs0vFAMZCROocl6MarwwY8XGUD/dh6hYaKY08Y+CsEP0SnI2UTQKJt0RqqWcBA== + "@types/hoist-non-react-statics@*": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" From aaa7b1848b9e5023f2745ee8e978e7ae0d2f9215 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Fri, 10 Feb 2023 16:52:22 +0900 Subject: [PATCH 21/61] Revert "chore: toast ui Add dependencieds" This reverts commit d51b6467f95f7b5327206dedb05d5a340edd82b1. --- package.json | 1 - yarn.lock | 9 ++------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 942fb347..262af290 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "typescript": "4.9.5" }, "devDependencies": { - "@toast-ui/select-box": "^1.1.0", "@types/lodash": "^4.14.191", "@types/node": "18.13.0", "@types/react": "18.0.27", diff --git a/yarn.lock b/yarn.lock index 74464155..f25ea9e2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -430,11 +430,6 @@ dependencies: "@toast-ui/editor" "^3.2.1" -"@toast-ui/select-box@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@toast-ui/select-box/-/select-box-1.1.0.tgz#eee7859054b192cbdce3c661de33e2b0be3bd343" - integrity sha512-arLYZ0xN2cmrvyB84SIS2NDkNs0vFAMZCROocl6MarwwY8XGUD/dh6hYaKY08Y+CsEP0SnI2UTQKJt0RqqWcBA== - "@types/hoist-non-react-statics@*": version "3.3.1" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" @@ -1436,7 +1431,7 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@8.33.0: +eslint@^8.0.1: version "8.33.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.33.0.tgz#02f110f32998cb598c6461f24f4d306e41ca33d7" integrity sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA== @@ -3083,7 +3078,7 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@4.9.5: +typescript@*: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== From e48ad539b57394aa7273e3e6f6b0d78b5122fdc7 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Fri, 10 Feb 2023 20:47:22 +0900 Subject: [PATCH 22/61] =?UTF-8?q?feat:=20DropDown.tsx:=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 로직부분 우선 처리 #8 --- Components/Common/DropDown.tsx | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 Components/Common/DropDown.tsx diff --git a/Components/Common/DropDown.tsx b/Components/Common/DropDown.tsx new file mode 100644 index 00000000..49b1f8d5 --- /dev/null +++ b/Components/Common/DropDown.tsx @@ -0,0 +1,36 @@ +import React from "react"; + +interface Options { + options: Option[]; + defaultValue: number | string; +} +interface Option { + value: number | string; +} +/** + * @returns {value} - 드롭다운 option + * @example + * + * const data = [...{value: number | string}] + */ +const DropDown = ({ defaultValue, options }: Options) => { + const handleChange = (e: React.ChangeEvent) => { + e.preventDefault(); + }; + + return ( + + ); +}; + +export default DropDown; From 4d6f7496103f867923a5238e05ec7d1e3d5c5d8f Mon Sep 17 00:00:00 2001 From: hyoloui Date: Fri, 10 Feb 2023 21:09:56 +0900 Subject: [PATCH 23/61] =?UTF-8?q?style:=20DropDown=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #8 --- Components/Common/DropDown.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Components/Common/DropDown.tsx b/Components/Common/DropDown.tsx index 49b1f8d5..1e54a32c 100644 --- a/Components/Common/DropDown.tsx +++ b/Components/Common/DropDown.tsx @@ -1,4 +1,5 @@ import React from "react"; +import styled from "styled-components"; interface Options { options: Option[]; @@ -7,6 +8,7 @@ interface Options { interface Option { value: number | string; } + /** * @returns {value} - 드롭다운 option * @example @@ -19,7 +21,7 @@ const DropDown = ({ defaultValue, options }: Options) => { }; return ( - {options.map((option) => ( ))} - + ); }; export default DropDown; + +const Select = styled.select` + display: flex; + padding: 8px 8px; + border: 1px solid; + border-radius: 4px; + color: inherit; + &:focus { + border-color: red; + } +`; From d359b1b361342f58adb5165d2410c7e45dfe9048 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Fri, 10 Feb 2023 21:24:20 +0900 Subject: [PATCH 24/61] =?UTF-8?q?feat:=20DropDown=20types=20=EA=B0=84?= =?UTF-8?q?=EC=86=8C=ED=99=94=20#8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/Common/DropDown.tsx | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Components/Common/DropDown.tsx b/Components/Common/DropDown.tsx index 1e54a32c..7a0ced10 100644 --- a/Components/Common/DropDown.tsx +++ b/Components/Common/DropDown.tsx @@ -2,15 +2,12 @@ import React from "react"; import styled from "styled-components"; interface Options { - options: Option[]; + options: number[] | string[]; defaultValue: number | string; } -interface Option { - value: number | string; -} /** - * @returns {value} - 드롭다운 option + * @returns {options} - 드롭다운 option[] * @example * * const data = [...{value: number | string}] @@ -23,12 +20,8 @@ const DropDown = ({ defaultValue, options }: Options) => { return ( From 6d43e06da3a884bf271229b2159be896d2999925 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Sat, 11 Feb 2023 00:30:57 +0900 Subject: [PATCH 25/61] =?UTF-8?q?refac:=20DropDown=20=ED=94=BC=EB=93=9C?= =?UTF-8?q?=EB=B0=B1=20=EB=B0=98=EC=98=81=20-=20=ED=94=BC=EB=93=9C?= =?UTF-8?q?=EB=B0=B1=20=EB=B0=98=EC=98=81=ED=95=98=EC=97=AC=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EC=99=84=EB=A3=8C=20=ED=96=88=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.=20@Jeremy-Kr=20@nno3onn=20@arch-spatula?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #8 --- Components/Common/DropDown.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Components/Common/DropDown.tsx b/Components/Common/DropDown.tsx index 7a0ced10..3d04e670 100644 --- a/Components/Common/DropDown.tsx +++ b/Components/Common/DropDown.tsx @@ -1,9 +1,9 @@ import React from "react"; import styled from "styled-components"; -interface Options { - options: number[] | string[]; - defaultValue: number | string; +interface DropdownProps { + options: T[]; + defaultValue: T; } /** @@ -12,7 +12,10 @@ interface Options { * * const data = [...{value: number | string}] */ -const DropDown = ({ defaultValue, options }: Options) => { +const DropDown = ({ + defaultValue, + options, +}: DropdownProps) => { const handleChange = (e: React.ChangeEvent) => { e.preventDefault(); }; @@ -32,9 +35,9 @@ export default DropDown; const Select = styled.select` display: flex; - padding: 8px 8px; + padding: 0.5rem 0.5rem; border: 1px solid; - border-radius: 4px; + border-radius: 0.25rem; color: inherit; &:focus { border-color: red; From ac9015343516020fa13fb835725edaa51ff8f0de Mon Sep 17 00:00:00 2001 From: hyoloui Date: Sat, 11 Feb 2023 01:23:59 +0900 Subject: [PATCH 26/61] =?UTF-8?q?refac:=20DropDown=20type=20-=EB=93=9C?= =?UTF-8?q?=EB=A1=AD=EB=8B=A4=EC=9A=B4=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=EC=97=90=20=EC=A0=84=EB=8B=AC=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=ED=94=84=EB=A1=AD=EC=8A=A4=20=ED=83=80=EC=9E=85=EC=9D=84=20?= =?UTF-8?q?=EC=A0=9C=EB=84=A4=EB=A6=AD=EC=9D=84=20=ED=99=9C=EC=9A=A9?= =?UTF-8?q?=ED=96=88=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #8 --- Components/Common/DropDown.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Components/Common/DropDown.tsx b/Components/Common/DropDown.tsx index 3d04e670..517df8a2 100644 --- a/Components/Common/DropDown.tsx +++ b/Components/Common/DropDown.tsx @@ -1,9 +1,9 @@ import React from "react"; import styled from "styled-components"; -interface DropdownProps { - options: T[]; +interface DropDownProps { defaultValue: T; + options: T[]; } /** @@ -15,7 +15,7 @@ interface DropdownProps { const DropDown = ({ defaultValue, options, -}: DropdownProps) => { +}: DropDownProps) => { const handleChange = (e: React.ChangeEvent) => { e.preventDefault(); }; From 237b211c7d3931305d77c4327d83a0dc68897559 Mon Sep 17 00:00:00 2001 From: Yunjunho Date: Fri, 10 Feb 2023 19:27:43 +0900 Subject: [PATCH 27/61] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=83=9D=EC=84=B1=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/Common/AuthLoginButton.tsx | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Components/Common/AuthLoginButton.tsx diff --git a/Components/Common/AuthLoginButton.tsx b/Components/Common/AuthLoginButton.tsx new file mode 100644 index 00000000..45a1321b --- /dev/null +++ b/Components/Common/AuthLoginButton.tsx @@ -0,0 +1,48 @@ +import styled from "styled-components"; + +interface AuthLoginButtonProps { + handleLogin: any; + children: string; +} + +const AuthLoginButton = ({ handleLogin, children }: AuthLoginButtonProps) => { + return {children}; +}; + +const LoginButton = styled.button` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + margin: 0.625rem; + padding: 0rem 1rem; + gap: 0.125rem; + + width: 27.1875rem; + height: 3.6875rem; + + border: 0.0625rem solid #333333; + border-radius: 6.25rem; + + flex: none; + order: 0; + flex-grow: 0; + + font-family: "Noto Sans KR"; + font-style: normal; + font-weight: 400; + font-size: 18px; + line-height: 26px; + + display: flex; + align-items: center; + text-align: center; + + cursor: pointer; + + :hover { + background-color: lightgray; + } +`; + +export default AuthLoginButton; From 49a40e8e73919b2c4c2e4850bcca0dae7d715bcc Mon Sep 17 00:00:00 2001 From: Yunjunho Date: Fri, 10 Feb 2023 19:55:09 +0900 Subject: [PATCH 28/61] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20export=20=EC=8B=A0=EA=B8=B0=EC=88=A0=20?= =?UTF-8?q?=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/Common/AuthLoginButton.tsx | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/Components/Common/AuthLoginButton.tsx b/Components/Common/AuthLoginButton.tsx index 45a1321b..462b1deb 100644 --- a/Components/Common/AuthLoginButton.tsx +++ b/Components/Common/AuthLoginButton.tsx @@ -1,22 +1,11 @@ import styled from "styled-components"; -interface AuthLoginButtonProps { - handleLogin: any; - children: string; -} - -const AuthLoginButton = ({ handleLogin, children }: AuthLoginButtonProps) => { - return {children}; -}; - const LoginButton = styled.button` display: flex; flex-direction: row; justify-content: center; align-items: center; margin: 0.625rem; - padding: 0rem 1rem; - gap: 0.125rem; width: 27.1875rem; height: 3.6875rem; @@ -30,9 +19,7 @@ const LoginButton = styled.button` font-family: "Noto Sans KR"; font-style: normal; - font-weight: 400; - font-size: 18px; - line-height: 26px; + font-size: 1.125rem; display: flex; align-items: center; @@ -45,4 +32,4 @@ const LoginButton = styled.button` } `; -export default AuthLoginButton; +export default LoginButton; From 150079841366f29f134d013d4cd5fdd1fa9b77b7 Mon Sep 17 00:00:00 2001 From: Yunjunho Date: Fri, 10 Feb 2023 22:49:39 +0900 Subject: [PATCH 29/61] =?UTF-8?q?feat:=20=EC=93=B8=EB=8D=B0=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/Common/AuthLoginButton.tsx | 11 +---------- pages/index.tsx | 2 ++ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Components/Common/AuthLoginButton.tsx b/Components/Common/AuthLoginButton.tsx index 462b1deb..019bae09 100644 --- a/Components/Common/AuthLoginButton.tsx +++ b/Components/Common/AuthLoginButton.tsx @@ -2,7 +2,6 @@ import styled from "styled-components"; const LoginButton = styled.button` display: flex; - flex-direction: row; justify-content: center; align-items: center; margin: 0.625rem; @@ -10,21 +9,13 @@ const LoginButton = styled.button` width: 27.1875rem; height: 3.6875rem; - border: 0.0625rem solid #333333; + border: 1px solid #333333; border-radius: 6.25rem; - flex: none; - order: 0; - flex-grow: 0; - font-family: "Noto Sans KR"; font-style: normal; font-size: 1.125rem; - display: flex; - align-items: center; - text-align: center; - cursor: pointer; :hover { diff --git a/pages/index.tsx b/pages/index.tsx index 9b0ae03e..7411a40a 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,4 +1,5 @@ import Head from "next/head"; +import LoginButton from "@/Components/Common/AuthLoginButton"; const Home = () => { return ( @@ -10,6 +11,7 @@ const Home = () => {
start
+ 카카오로 로그인 ); }; From fc3469b8caf460443aedf9238a5e632a36bceb57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A4=EC=A4=80=ED=98=B8?= <50473516+yunjunhojj@users.noreply.github.com> Date: Fri, 10 Feb 2023 22:50:36 +0900 Subject: [PATCH 30/61] Update index.tsx --- pages/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index 7411a40a..9b0ae03e 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,5 +1,4 @@ import Head from "next/head"; -import LoginButton from "@/Components/Common/AuthLoginButton"; const Home = () => { return ( @@ -11,7 +10,6 @@ const Home = () => {
start
- 카카오로 로그인 ); }; From 9785c38ffe991c80aec0edc7e7084a755e3a7771 Mon Sep 17 00:00:00 2001 From: Jeremy-kr Date: Sat, 11 Feb 2023 01:02:48 +0900 Subject: [PATCH 31/61] =?UTF-8?q?feat(SideBar):=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EB=93=9C=EB=B0=94=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이제 사이드바를 사용할 수 있습니다. #3 --- Components/Main/LargeCategory.tsx | 57 +++++++++++ Components/Main/SideBar.tsx | 159 ++++++++++++++++++++++++++++++ public/icons/bottom_arrow.svg | 3 + public/icons/check.svg | 3 + 4 files changed, 222 insertions(+) create mode 100644 Components/Main/LargeCategory.tsx create mode 100644 Components/Main/SideBar.tsx create mode 100644 public/icons/bottom_arrow.svg create mode 100644 public/icons/check.svg diff --git a/Components/Main/LargeCategory.tsx b/Components/Main/LargeCategory.tsx new file mode 100644 index 00000000..47ff774a --- /dev/null +++ b/Components/Main/LargeCategory.tsx @@ -0,0 +1,57 @@ +import Image from "next/image"; +import React from "react"; +import styled from "styled-components"; +import bottom_arrow from "@/public/icons/bottom_arrow.svg"; + +interface LargeCategoryProps { + item: string; + selectedCategory: string[]; + setSelectedCategory: React.Dispatch>; +} + +const LargeCategoryContainer = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + height: 2rem; + margin-bottom: 1rem; + + &:hover { + cursor: pointer; + } + + &:last-of-type { + margin-bottom: 0; + } +`; + +const LargeCategoryItem = styled.span` + font-size: 1.25rem; +`; + +const LargeCategory = ({ + item, + selectedCategory, + setSelectedCategory, +}: LargeCategoryProps) => { + const onClickLargeCategory = (e: React.MouseEvent) => { + const target = e.target as HTMLElement; + const largeCategory = target.innerText; + + if (selectedCategory.includes(largeCategory)) { + setSelectedCategory( + selectedCategory.filter((category) => category !== largeCategory) + ); + return; + } + setSelectedCategory((prev) => [...prev, largeCategory]); + }; + return ( + onClickLargeCategory(e)}> + {item} + bottom_arrow + + ); +}; + +export default LargeCategory; diff --git a/Components/Main/SideBar.tsx b/Components/Main/SideBar.tsx new file mode 100644 index 00000000..01c9ca79 --- /dev/null +++ b/Components/Main/SideBar.tsx @@ -0,0 +1,159 @@ +import styled from "styled-components"; +import check from "@/public/icons/check.svg"; +import Image from "next/image"; +import { useState } from "react"; +import LargeCategory from "./LargeCategory"; + +const SideBarContainer = styled.aside` + display: flex; + flex-direction: column; + width: 18.75rem; + height: auto; + padding: 3.5rem 2.5rem 3.5rem 1.5rem; +`; + +const SideBarTitle = styled.span` + font-size: 1.5rem; +`; + +const SideBarHr = styled.hr` + width: 100%; + height: 1px; + border: none; + background-color: #ccc; + margin: 1.5rem 0; +`; + +const CategoryContainer = styled.div` + display: flex; + flex-direction: column; + width: 100%; + height: auto; +`; + +const SubCategoryItemsContainer = styled.div` + display: flex; + flex-direction: column; + height: auto; +`; + +interface SubCategoryItemProps { + selected: boolean; +} + +const SubCategoryContainer = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + height: 2.75rem; + padding: 0.625rem 0.625rem 0.625rem 1rem; + + ${({ selected }) => + selected && + ` + background-color: #f2f2f2; + font-weight: 500; + `} + + &:hover { + cursor: pointer; + background-color: #f2f2f2; + } +`; + +const SubCategoryItem = styled.span` + font-size: 1rem; +`; + +interface SubCategoryItemsType { + [key: string]: string[]; +} + +const SideBar = () => { + const [selectedCategory, setSelectedCategory] = useState([]); + const [selectedSubCategory, setSelectedSubCategory] = useState([]); + + const largeCategoryItems = [ + "Web", + "App", + "Software", + "Data", + "Web3", + "DevOps", + "IOT&Embedded", + "Security", + ]; + + const subCategoryItems: SubCategoryItemsType = { + Web: ["Front-End", "Back-End", "Full-Stack"], + App: ["iOS", "Android", "Flutter", "React Native"], + Software: ["사무자동화", "공장자동화", "ERP", "유니티", "언리얼"], + Data: ["데이터 엔지니어", "머신러닝 엔지니어", "데이터 사이언스"], + Web3: ["기타"], + DevOps: ["기타"], + "IOT&Embedded": ["기타"], + Security: ["기타"], + }; + + const onClickSubCategory = (e: React.MouseEvent) => { + const target = e.target as HTMLElement; + const subCategory = target.innerText; + + if (selectedSubCategory.includes(subCategory)) { + setSelectedSubCategory( + selectedSubCategory.filter((item) => item !== subCategory) + ); + return; + } + setSelectedSubCategory((prev) => [...prev, subCategory]); + }; + + return ( + + 전체 + + + {largeCategoryItems.map((item: string) => ( + <> + + + {selectedCategory.includes(item) && + subCategoryItems[item].map((subItem) => + selectedSubCategory.includes(subItem) ? ( + onClickSubCategory(e)} + selected={selectedSubCategory.includes(subItem)} + > + {subItem} + + + ) : ( + onClickSubCategory(e)} + selected={false} + > + {subItem} + + ) + )} + + + ))} + + + ); +}; + +export default SideBar; diff --git a/public/icons/bottom_arrow.svg b/public/icons/bottom_arrow.svg new file mode 100644 index 00000000..93e08a9f --- /dev/null +++ b/public/icons/bottom_arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/check.svg b/public/icons/check.svg new file mode 100644 index 00000000..6fe2a3e9 --- /dev/null +++ b/public/icons/check.svg @@ -0,0 +1,3 @@ + + + From fdec648198586eda37af0b745c8e1ec4ed782a4c Mon Sep 17 00:00:00 2001 From: hyoloui Date: Sat, 11 Feb 2023 08:53:54 +0900 Subject: [PATCH 32/61] refactor: DropDown.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 불친절한 드롭다운 리펙토링 - 추후 스타일링 필요 #8 --- Components/Common/DropDown.tsx | 54 ++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/Components/Common/DropDown.tsx b/Components/Common/DropDown.tsx index 517df8a2..25a45b9f 100644 --- a/Components/Common/DropDown.tsx +++ b/Components/Common/DropDown.tsx @@ -1,29 +1,45 @@ -import React from "react"; +import React, { useState } from "react"; import styled from "styled-components"; -interface DropDownProps { - defaultValue: T; - options: T[]; +type ComponenetData = "birth_year" | "careerer"; +interface DropDownProps { + data: ComponenetData; } - /** - * @returns {options} - 드롭다운 option[] * @example - * - * const data = [...{value: number | string}] + * + * + * @TODO 컴포넌트별 스타일 분리 */ -const DropDown = ({ - defaultValue, - options, -}: DropDownProps) => { +const DropDown = ({ data }: DropDownProps) => { + const [selectValue, setSelectValue] = useState(""); + + const options: string[] = []; + // const thisYears = new Date(); + const years = Array.from( + { length: new Date().getFullYear() - 1950 + 1 }, + (_, i) => { + return new Date().getFullYear() - i; + } + ); + if (data === "birth_year") { + years.forEach((year) => options.push(String(year))); + } + if (data === "careerer") { + for (let i = 1; i < 20; i += 1) { + options.push(`${i}년차`); + } + options.unshift("신입"); + options.push("20년차 이상"); + } + const handleChange = (e: React.ChangeEvent) => { - e.preventDefault(); + setSelectValue(e.target.value); }; - return ( 프로젝트 기간 diff --git a/pages/post/post.tsx b/pages/post/post.tsx index 48388b24..e0bf600c 100644 --- a/pages/post/post.tsx +++ b/pages/post/post.tsx @@ -7,8 +7,8 @@ import { useState } from "react"; import dynamic from "next/dynamic"; /** - * @TODO 마크다운 * @TODO 코드블럭 + * @TODO Date recoil을 활용한 custom hook으로 리팩토링하기 */ const Post: NextPage = () => { @@ -16,6 +16,9 @@ const Post: NextPage = () => { const [subTitle, setSubTitle] = useState(""); const [imgFile, setImgFile] = useState(""); + const [startDate, setStartDate] = useState(new Date()); + const [endDate, setEndDate] = useState(new Date()); + const onClickTest = () => { console.log("hi"); }; @@ -45,7 +48,12 @@ const Post: NextPage = () => { imgFile={imgFile} setImgFile={setImgFile} /> - +
From b77ae74a0cf7ed53bb8b7df167de8b4cd69bced1 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Tue, 14 Feb 2023 20:10:37 +0900 Subject: [PATCH 44/61] =?UTF-8?q?feat(post):=20post=20page=20state=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - enter 해결 남았습니다 #5 --- Components/Post/ProjectInfo.tsx | 6 ++++++ Components/Post/ProjectInfoDropDown.tsx | 24 +++++++++++++++++------- pages/post/post.tsx | 4 ++++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/Components/Post/ProjectInfo.tsx b/Components/Post/ProjectInfo.tsx index 2e292406..163460ed 100644 --- a/Components/Post/ProjectInfo.tsx +++ b/Components/Post/ProjectInfo.tsx @@ -9,6 +9,8 @@ interface ProjectInfoDropDownProps { setStartDate: Dispatch>; endDate: Date; setEndDate: Dispatch>; + techStackInput: string[]; + setTechStackInput: Dispatch>; } const ProjectInfo = ({ @@ -16,6 +18,8 @@ const ProjectInfo = ({ setStartDate, endDate, setEndDate, + techStackInput, + setTechStackInput, }: ProjectInfoDropDownProps) => { const [openDropdown, setOpenDropdown] = useState(false); @@ -33,6 +37,8 @@ const ProjectInfo = ({ setStartDate={setStartDate} endDate={endDate} setEndDate={setEndDate} + techStackInput={techStackInput} + setTechStackInput={setTechStackInput} /> )} diff --git a/Components/Post/ProjectInfoDropDown.tsx b/Components/Post/ProjectInfoDropDown.tsx index e801e230..3751529f 100644 --- a/Components/Post/ProjectInfoDropDown.tsx +++ b/Components/Post/ProjectInfoDropDown.tsx @@ -1,11 +1,12 @@ import styled from "styled-components"; -import { ChangeEvent, Dispatch, SetStateAction, useState } from "react"; +import { Dispatch, SetStateAction } from "react"; import "react-datepicker/dist/react-datepicker.css"; import DatePicker from "react-datepicker"; import Tags from "../Common/Tags"; /** * @see https://www.youtube.com/shorts/4hpjO2onpNs + * @TODO 월 선택 안됨. 준호님 질문 */ interface ProjectInfoDropDownProps { @@ -13,17 +14,21 @@ interface ProjectInfoDropDownProps { setStartDate: Dispatch>; endDate: Date; setEndDate: Dispatch>; + techStackInput: string[]; + setTechStackInput: Dispatch>; } - const ProjectInfoDropDown = ({ startDate, setStartDate, endDate, setEndDate, + techStackInput, + setTechStackInput, }: ProjectInfoDropDownProps) => { - const [techStack, setTechStack] = useState(""); - const handleOnChange = (e: ChangeEvent) => { - setTechStack(e.target.value); + const handleOnChange = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + setTechStackInput((prev) => [...prev, e.currentTarget.value]); + } }; return ( @@ -36,8 +41,13 @@ const ProjectInfoDropDown = ({ 개발 스택 {/* input으로 받아 Tags로 전달 */} - - + + 프로젝트 기간 diff --git a/pages/post/post.tsx b/pages/post/post.tsx index e0bf600c..773bf0d4 100644 --- a/pages/post/post.tsx +++ b/pages/post/post.tsx @@ -19,6 +19,8 @@ const Post: NextPage = () => { const [startDate, setStartDate] = useState(new Date()); const [endDate, setEndDate] = useState(new Date()); + const [techStackInput, setTechStackInput] = useState([]); + const onClickTest = () => { console.log("hi"); }; @@ -53,6 +55,8 @@ const Post: NextPage = () => { setStartDate={setStartDate} endDate={endDate} setEndDate={setEndDate} + techStackInput={techStackInput} + setTechStackInput={setTechStackInput} />
From 05a1f6795da21d175bf80617821f66c6bc76c019 Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Tue, 14 Feb 2023 20:29:40 +0900 Subject: [PATCH 45/61] =?UTF-8?q?feat(ProjectInfo=20&=20DropDown,=20Post):?= =?UTF-8?q?=20=EC=97=94=ED=84=B0=EB=A1=9C=20tag=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - techStack tag를 input으로 추가가 가능하게 구현 #5 --- Components/Post/ProjectInfo.tsx | 12 +++++------ Components/Post/ProjectInfoDropDown.tsx | 27 +++++++++++++++---------- pages/post/post.tsx | 6 +++--- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/Components/Post/ProjectInfo.tsx b/Components/Post/ProjectInfo.tsx index 163460ed..0cb08d08 100644 --- a/Components/Post/ProjectInfo.tsx +++ b/Components/Post/ProjectInfo.tsx @@ -9,8 +9,8 @@ interface ProjectInfoDropDownProps { setStartDate: Dispatch>; endDate: Date; setEndDate: Dispatch>; - techStackInput: string[]; - setTechStackInput: Dispatch>; + techStack: string[]; + setTechStack: Dispatch>; } const ProjectInfo = ({ @@ -18,8 +18,8 @@ const ProjectInfo = ({ setStartDate, endDate, setEndDate, - techStackInput, - setTechStackInput, + techStack, + setTechStack, }: ProjectInfoDropDownProps) => { const [openDropdown, setOpenDropdown] = useState(false); @@ -37,8 +37,8 @@ const ProjectInfo = ({ setStartDate={setStartDate} endDate={endDate} setEndDate={setEndDate} - techStackInput={techStackInput} - setTechStackInput={setTechStackInput} + techStack={techStack} + setTechStack={setTechStack} /> )} diff --git a/Components/Post/ProjectInfoDropDown.tsx b/Components/Post/ProjectInfoDropDown.tsx index 3751529f..87d8544b 100644 --- a/Components/Post/ProjectInfoDropDown.tsx +++ b/Components/Post/ProjectInfoDropDown.tsx @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { Dispatch, SetStateAction } from "react"; +import { Dispatch, SetStateAction, useState } from "react"; import "react-datepicker/dist/react-datepicker.css"; import DatePicker from "react-datepicker"; import Tags from "../Common/Tags"; @@ -14,22 +14,27 @@ interface ProjectInfoDropDownProps { setStartDate: Dispatch>; endDate: Date; setEndDate: Dispatch>; - techStackInput: string[]; - setTechStackInput: Dispatch>; + techStack: string[]; + setTechStack: Dispatch>; } const ProjectInfoDropDown = ({ startDate, setStartDate, endDate, setEndDate, - techStackInput, - setTechStackInput, + techStack, + setTechStack, }: ProjectInfoDropDownProps) => { - const handleOnChange = (e: React.KeyboardEvent) => { + const [inputValue, setInputValue] = useState(""); + const handleOnPush = (e: React.KeyboardEvent) => { if (e.key === "Enter") { - setTechStackInput((prev) => [...prev, e.currentTarget.value]); + setTechStack((prev) => [...prev, inputValue]); + setInputValue(""); } }; + const handleOnChange = (e: React.ChangeEvent) => { + setInputValue(e.target.value); + }; return ( @@ -41,12 +46,12 @@ const ProjectInfoDropDown = ({ 개발 스택 {/* input으로 받아 Tags로 전달 */} - + diff --git a/pages/post/post.tsx b/pages/post/post.tsx index 773bf0d4..4bb9bbbb 100644 --- a/pages/post/post.tsx +++ b/pages/post/post.tsx @@ -19,7 +19,7 @@ const Post: NextPage = () => { const [startDate, setStartDate] = useState(new Date()); const [endDate, setEndDate] = useState(new Date()); - const [techStackInput, setTechStackInput] = useState([]); + const [techStack, setTechStack] = useState([]); const onClickTest = () => { console.log("hi"); @@ -55,8 +55,8 @@ const Post: NextPage = () => { setStartDate={setStartDate} endDate={endDate} setEndDate={setEndDate} - techStackInput={techStackInput} - setTechStackInput={setTechStackInput} + techStack={techStack} + setTechStack={setTechStack} />
From aa67f7c223e5a0015916a2a093f22e6d34e8ff1a Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Tue, 14 Feb 2023 20:36:05 +0900 Subject: [PATCH 46/61] =?UTF-8?q?feat(ProjectInfoDropDown):=20FieldDropDow?= =?UTF-8?q?n=20=EA=B5=AC=ED=98=84=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FieldDropDown의 UI가 보이고 안 보이고 구현 중 #5 --- Components/Post/ProjectInfoDropDown.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Components/Post/ProjectInfoDropDown.tsx b/Components/Post/ProjectInfoDropDown.tsx index 87d8544b..9e03bfcb 100644 --- a/Components/Post/ProjectInfoDropDown.tsx +++ b/Components/Post/ProjectInfoDropDown.tsx @@ -36,12 +36,18 @@ const ProjectInfoDropDown = ({ setInputValue(e.target.value); }; + const [categoryVisible, setCategoryVisible] = useState(false); + + const handleShowCategory = () => {}; + return ( 카테고리 {/* input으로 받아줄 state 생성 */} - 카테고리를 선택해주세요. + + 카테고리를 선택해주세요. + 개발 스택 From 97d954ac1b85a72c5c1bd90ea769d93e18173060 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Tue, 14 Feb 2023 21:42:11 +0900 Subject: [PATCH 47/61] feat(ProjectInfo & DropDown, post, FiledDropDown): post page update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 포스트 페이지 작업 중 #5 --- .../{edit-post => Post}/FieldDropDown.tsx | 47 ++++++++++++++----- Components/Post/ProjectInfo.tsx | 1 - Components/Post/ProjectInfoDropDown.tsx | 19 +++++--- pages/post/post.tsx | 4 ++ 4 files changed, 51 insertions(+), 20 deletions(-) rename Components/{edit-post => Post}/FieldDropDown.tsx (82%) diff --git a/Components/edit-post/FieldDropDown.tsx b/Components/Post/FieldDropDown.tsx similarity index 82% rename from Components/edit-post/FieldDropDown.tsx rename to Components/Post/FieldDropDown.tsx index c83e3610..e600d0d9 100644 --- a/Components/edit-post/FieldDropDown.tsx +++ b/Components/Post/FieldDropDown.tsx @@ -1,4 +1,10 @@ -import { useReducer } from "react"; +import { + Dispatch, + SetStateAction, + useEffect, + useReducer, + useState, +} from "react"; import styled from "styled-components"; /** @@ -48,13 +54,20 @@ const reducer = (_state: string[], action: { type: Field }): string[] => { return ["기타"]; } }; - -const FieldDropDown = () => { +interface FieldDropDownProps { + setSelectedItem: Dispatch>; +} +const FieldDropDown = ({ setSelectedItem }: FieldDropDownProps) => { const [state, dispatch] = useReducer(reducer, initialState); + const handleLargeCategory = (item: Field) => { dispatch({ type: item }); }; + const handleOverlayItem = (item: string) => { + setSelectedItem(item); + }; + return (
    @@ -70,7 +83,11 @@ const FieldDropDown = () => {
      {state.map((item) => ( - + handleOverlayItem(item)} + cursor + > {item} ))} @@ -79,9 +96,22 @@ const FieldDropDown = () => { ); }; +const FieldDropDownContainer = styled.div` + width: 21.5rem; + box-shadow: 0px 0.25rem 0.25rem rgba(0, 0, 0, 0.25); + border: 1px solid #cccccc; + display: flex; + border-radius: 0.2rem; + gap: 0; + position: absolute; + background-color: #fff; + z-index: 21; +`; + const FiledItemContainer = styled.li<{ key?: string; onMouseOver?: () => void; + onClick?: () => void; cursor?: boolean; }>` padding: 0.75rem; @@ -92,15 +122,6 @@ const FiledItemContainer = styled.li<{ } `; -const FieldDropDownContainer = styled.div` - width: 21.5rem; - box-shadow: 0px 0.25rem 0.25rem rgba(0, 0, 0, 0.25); - border: 1px solid #cccccc; - display: flex; - border-radius: 0.2rem; - gap: 0; -`; - const Divider = styled.hr` padding: 0; margin: 0; diff --git a/Components/Post/ProjectInfo.tsx b/Components/Post/ProjectInfo.tsx index 0cb08d08..a4580914 100644 --- a/Components/Post/ProjectInfo.tsx +++ b/Components/Post/ProjectInfo.tsx @@ -46,7 +46,6 @@ const ProjectInfo = ({ }; const DropdownContainer = styled.div` - width: 98.75rem; height: 3.6569rem; border: 1px solid #cccccc; diff --git a/Components/Post/ProjectInfoDropDown.tsx b/Components/Post/ProjectInfoDropDown.tsx index 9e03bfcb..ad90bcda 100644 --- a/Components/Post/ProjectInfoDropDown.tsx +++ b/Components/Post/ProjectInfoDropDown.tsx @@ -3,10 +3,11 @@ import { Dispatch, SetStateAction, useState } from "react"; import "react-datepicker/dist/react-datepicker.css"; import DatePicker from "react-datepicker"; import Tags from "../Common/Tags"; +import FieldDropDown from "./FieldDropDown"; /** * @see https://www.youtube.com/shorts/4hpjO2onpNs - * @TODO 월 선택 안됨. 준호님 질문 + * @TODO 월 선택 안됨 (z-index) */ interface ProjectInfoDropDownProps { @@ -26,6 +27,7 @@ const ProjectInfoDropDown = ({ setTechStack, }: ProjectInfoDropDownProps) => { const [inputValue, setInputValue] = useState(""); + const [selectedItem, setSelectedItem] = useState(""); const handleOnPush = (e: React.KeyboardEvent) => { if (e.key === "Enter") { setTechStack((prev) => [...prev, inputValue]); @@ -38,20 +40,23 @@ const ProjectInfoDropDown = ({ const [categoryVisible, setCategoryVisible] = useState(false); - const handleShowCategory = () => {}; + const handleShowCategory = () => { + setCategoryVisible((prev) => !prev); + }; return ( 카테고리 - {/* input으로 받아줄 state 생성 */} 카테고리를 선택해주세요. + {categoryVisible && ( + + )} 개발 스택 - {/* input으로 받아 Tags로 전달 */} { From b77aa016696bc0fbb41f0fe97fff2cd5cc89c4a0 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Wed, 15 Feb 2023 09:25:24 +0900 Subject: [PATCH 48/61] =?UTF-8?q?fix(post):=20@TODO=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20#5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/post/post.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pages/post/post.tsx b/pages/post/post.tsx index 5f60c356..7e8270a0 100644 --- a/pages/post/post.tsx +++ b/pages/post/post.tsx @@ -9,6 +9,8 @@ import dynamic from "next/dynamic"; /** * @TODO 코드블럭 * @TODO 게시 전 입력창 추가(인원, 기간 등 - 피그마 참고) + * @TODO file(img) input 에서 color picker로 변경 + * @TODO date picker z-index 해결 * @TODO Date recoil을 활용한 custom hook으로 리팩토링하기 * @TODO 개발스택 UI my-page 참고 * @TODO 카테고리 중복 선택 , 보여주는 UI From 99849c8543813b67d3b958a78cb3b23347ff40a8 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Wed, 15 Feb 2023 09:27:48 +0900 Subject: [PATCH 49/61] =?UTF-8?q?fix(post):=20=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20#5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/post/post.tsx => Components/Post/Post.tsx | 2 +- pages/create-post.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename pages/post/post.tsx => Components/Post/Post.tsx (96%) diff --git a/pages/post/post.tsx b/Components/Post/Post.tsx similarity index 96% rename from pages/post/post.tsx rename to Components/Post/Post.tsx index 7e8270a0..55759be0 100644 --- a/pages/post/post.tsx +++ b/Components/Post/Post.tsx @@ -31,7 +31,7 @@ const Post: NextPage = () => { console.log("hi"); }; - const PostEditor = dynamic(() => import("../../Components/Post/PostEditor"), { + const PostEditor = dynamic(() => import("./PostEditor"), { ssr: false, }); diff --git a/pages/create-post.tsx b/pages/create-post.tsx index 9e6569c1..4212d8d7 100644 --- a/pages/create-post.tsx +++ b/pages/create-post.tsx @@ -1,6 +1,6 @@ import GNB from "@/Components/Layouts/GNB"; +import Post from "@/Components/Post/post"; import { NextPage, GetServerSideProps } from "next"; -import Post from "./post/post"; const CreatePostPage: NextPage = () => { return ( From a00363dc86cc08630e42bb4c16bdafd5bff45677 Mon Sep 17 00:00:00 2001 From: nno3onn Date: Wed, 15 Feb 2023 10:24:03 +0900 Subject: [PATCH 50/61] =?UTF-8?q?feat(PostPage):=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EC=A0=9D=ED=8A=B8=20=EC=A0=95=EB=B3=B4=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EC=A4=91=20-=20=EA=B0=9C=EB=B0=9C=20=EC=8A=A4=ED=83=9D=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C=20-=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EA=B8=80=20=EA=B3=B5=EA=B0=9C=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=20-=20=ED=82=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=ED=83=9C=EA=B7=B8=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C=20?= =?UTF-8?q?-=20=ED=95=A8=EA=BB=98=ED=95=9C=20=EC=82=AC=EB=9E=8C=EB=93=A4?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20=EC=A7=84=ED=96=89=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Post Page 개발 #5 by @nno3onn --- Components/{MyPage => Common/Skill}/Skill.tsx | 0 .../{MyPage => Common/Skill}/SkillList.tsx | 5 +- Components/MyPage/EditProfileContainer.tsx | 3 +- Components/Post/Post.tsx | 10 ++ Components/Post/ProjectInfo.tsx | 20 +++ Components/Post/ProjectInfoDropDown.tsx | 141 ++++++++++++------ Components/Post/WithPeople.tsx | 68 +++++++++ pages/create-post.tsx | 2 +- yarn.lock | 16 +- 9 files changed, 215 insertions(+), 50 deletions(-) rename Components/{MyPage => Common/Skill}/Skill.tsx (100%) rename Components/{MyPage => Common/Skill}/SkillList.tsx (86%) create mode 100644 Components/Post/WithPeople.tsx diff --git a/Components/MyPage/Skill.tsx b/Components/Common/Skill/Skill.tsx similarity index 100% rename from Components/MyPage/Skill.tsx rename to Components/Common/Skill/Skill.tsx diff --git a/Components/MyPage/SkillList.tsx b/Components/Common/Skill/SkillList.tsx similarity index 86% rename from Components/MyPage/SkillList.tsx rename to Components/Common/Skill/SkillList.tsx index 0e61cc57..6d5fbfb1 100644 --- a/Components/MyPage/SkillList.tsx +++ b/Components/Common/Skill/SkillList.tsx @@ -3,11 +3,12 @@ import styled from "styled-components"; import Skill, { commonStyle } from "./Skill"; interface SkillPickerProps { + text: string; editSkills: string[]; setEditSkills: Dispatch>; } -const SkillList = ({ editSkills, setEditSkills }: SkillPickerProps) => { +const SkillList = ({ text, editSkills, setEditSkills }: SkillPickerProps) => { const addSkill = () => { if (editSkills[editSkills.length - 1] !== "") setEditSkills([...editSkills, ""]); @@ -29,7 +30,7 @@ const SkillList = ({ editSkills, setEditSkills }: SkillPickerProps) => { onDelete={onDelete} /> ))} - + 스킬 입력 + + {text} ); }; diff --git a/Components/MyPage/EditProfileContainer.tsx b/Components/MyPage/EditProfileContainer.tsx index 4f42cffd..df4f8030 100644 --- a/Components/MyPage/EditProfileContainer.tsx +++ b/Components/MyPage/EditProfileContainer.tsx @@ -7,11 +7,11 @@ import { Dispatch, useState } from "react"; import styled from "styled-components"; import DefaultButton from "../Common/DefaultButton"; import DropDown from "../Common/DropDown"; +import SkillList from "../Common/Skill/SkillList"; import Toggle from "../Common/Toggle"; import PositionTag from "./PositionTag"; import ProfileContainer from "./ProfileContainer"; import { ContentContainer, ContentWrapper } from "./ShowProfileContainer"; -import SkillList from "./SkillList"; import SwitchButton from "./SwitchButton"; const fieldList = [ @@ -108,6 +108,7 @@ const EditProfileContainer = ({

      스킬

      diff --git a/Components/Post/Post.tsx b/Components/Post/Post.tsx index 55759be0..676339d9 100644 --- a/Components/Post/Post.tsx +++ b/Components/Post/Post.tsx @@ -5,6 +5,7 @@ import PostTitle from "@/Components/Post/PostTitle"; import ProjectInfo from "@/Components/Post/ProjectInfo"; import { useState } from "react"; import dynamic from "next/dynamic"; +import { WithPersonType } from "./WithPeople"; /** * @TODO 코드블럭 @@ -26,6 +27,9 @@ const Post: NextPage = () => { const [endDate, setEndDate] = useState(new Date()); const [techStack, setTechStack] = useState([]); + const [tag, setTag] = useState([]); + const [isPublic, setIsPublic] = useState(false); + const [people, setPeople] = useState([]); const onClickTest = () => { console.log("hi"); @@ -63,6 +67,12 @@ const Post: NextPage = () => { setEndDate={setEndDate} techStack={techStack} setTechStack={setTechStack} + tag={tag} + setTag={setTag} + isPublic={isPublic} + setIsPublic={setIsPublic} + people={people} + setPeople={setPeople} />
diff --git a/Components/Post/ProjectInfo.tsx b/Components/Post/ProjectInfo.tsx index a4580914..55590b5e 100644 --- a/Components/Post/ProjectInfo.tsx +++ b/Components/Post/ProjectInfo.tsx @@ -3,6 +3,7 @@ import styled from "styled-components"; import { Dispatch, SetStateAction, useState } from "react"; import arrow_down from "@/public/images/arrow_down.jpg"; import ProjectInfoDropDown from "./ProjectInfoDropDown"; +import { WithPersonType } from "./WithPeople"; interface ProjectInfoDropDownProps { startDate: Date; @@ -11,6 +12,12 @@ interface ProjectInfoDropDownProps { setEndDate: Dispatch>; techStack: string[]; setTechStack: Dispatch>; + tag: string[]; + setTag: Dispatch>; + isPublic: boolean; + setIsPublic: Dispatch>; + people: WithPersonType[]; + setPeople: Dispatch>; } const ProjectInfo = ({ @@ -20,6 +27,12 @@ const ProjectInfo = ({ setEndDate, techStack, setTechStack, + tag, + setTag, + isPublic, + setIsPublic, + people, + setPeople, }: ProjectInfoDropDownProps) => { const [openDropdown, setOpenDropdown] = useState(false); @@ -39,6 +52,12 @@ const ProjectInfo = ({ setEndDate={setEndDate} techStack={techStack} setTechStack={setTechStack} + tag={tag} + setTag={setTag} + isPublic={isPublic} + setIsPublic={setIsPublic} + people={people} + setPeople={setPeople} /> )} @@ -65,6 +84,7 @@ const DropdownButton = styled.button` border: none; margin-right: 2.5rem; background-color: white; + cursor: pointer; `; const DropdownImage = styled(Image)` diff --git a/Components/Post/ProjectInfoDropDown.tsx b/Components/Post/ProjectInfoDropDown.tsx index ad90bcda..897eca32 100644 --- a/Components/Post/ProjectInfoDropDown.tsx +++ b/Components/Post/ProjectInfoDropDown.tsx @@ -2,8 +2,10 @@ import styled from "styled-components"; import { Dispatch, SetStateAction, useState } from "react"; import "react-datepicker/dist/react-datepicker.css"; import DatePicker from "react-datepicker"; -import Tags from "../Common/Tags"; import FieldDropDown from "./FieldDropDown"; +import SkillList from "../Common/Skill/SkillList"; +import Toggle from "../Common/Toggle"; +import WithPeople, { WithPersonType } from "./WithPeople"; /** * @see https://www.youtube.com/shorts/4hpjO2onpNs @@ -17,7 +19,14 @@ interface ProjectInfoDropDownProps { setEndDate: Dispatch>; techStack: string[]; setTechStack: Dispatch>; + tag: string[]; + setTag: Dispatch>; + isPublic: boolean; + setIsPublic: Dispatch>; + people: WithPersonType[]; + setPeople: Dispatch>; } + const ProjectInfoDropDown = ({ startDate, setStartDate, @@ -25,9 +34,16 @@ const ProjectInfoDropDown = ({ setEndDate, techStack, setTechStack, + tag, + setTag, + isPublic, + setIsPublic, + people, + setPeople, }: ProjectInfoDropDownProps) => { const [inputValue, setInputValue] = useState(""); const [selectedItem, setSelectedItem] = useState(""); + const handleOnPush = (e: React.KeyboardEvent) => { if (e.key === "Enter") { setTechStack((prev) => [...prev, inputValue]); @@ -46,50 +62,67 @@ const ProjectInfoDropDown = ({ return ( - - 카테고리 - - 카테고리를 선택해주세요. - {categoryVisible && ( - - )} - - - - 개발 스택 - - - - - 프로젝트 기간 - - setStartDate(date)} - selectsStart - startDate={startDate} - endDate={endDate} - /> - ~ - setEndDate(date)} - selectsEnd - startDate={startDate} - endDate={endDate} - minDate={startDate} + + + 카테고리 + + 카테고리를 선택해주세요. + {categoryVisible && ( + + )} + + + + 개발 스택 + - - + + + 프로젝트 기간 + + setStartDate(date)} + selectsStart + startDate={startDate} + endDate={endDate} + /> + ~ + setEndDate(date)} + selectsEnd + startDate={startDate} + endDate={endDate} + minDate={startDate} + /> + + + + + + 함께한 사람들 + + + + 키워드 태그 + + + + 게시물 공개 + + +

비공개

+
+
+
); }; @@ -100,11 +133,21 @@ const ProjectInfoDropDownContainer = styled.div` margin-top: 2px; border: 1px solid #cccccc; + display: grid; + grid-template-columns: 1fr 1fr; +`; + +const ProjectInfoContainer = styled.div` display: flex; flex-direction: column; justify-content: space-around; `; +const ProjectInfoWrapper = styled.div` + display: grid; + grid-template-columns: 1fr 4fr; +`; + const CategoryContainer = styled.div` display: flex; `; @@ -124,6 +167,16 @@ const DatePickerContainer = styled.div` display: flex; `; +const ToggleWrapper = styled.div` + display: flex; + gap: 12px; + align-items: center; + p { + color: #999999; + font-size: 13px; + } +`; + const StyledDatePicker = styled(DatePicker)` width: 7.8125rem; diff --git a/Components/Post/WithPeople.tsx b/Components/Post/WithPeople.tsx new file mode 100644 index 00000000..2bec0724 --- /dev/null +++ b/Components/Post/WithPeople.tsx @@ -0,0 +1,68 @@ +import { Dispatch, SetStateAction } from "react"; +import styled from "styled-components"; + +export interface WithPersonType { + name: string; + field: string; + github: string; +} + +interface WithPeopleProps { + people: WithPersonType[]; + setPeople: Dispatch>; +} + +const WithPeople = ({ people, setPeople }: WithPeopleProps) => { + const addPerson = () => { + setPeople((prev: WithPersonType) => + prev.push({ name: "", field: "", github: "" }) + ); + }; + const changeName = (idx: number) => {}; + + const changeField = (idx: number) => {}; + + const changeGithub = (idx: number) => {}; + return ( + + {/* {people && + people.map((person, idx) => ( + + + + + + ))} */} + + 참여자 추가 + + ); +}; + +const WithPeopleContainer = styled.div` + display: flex; + flex-direction: column; +`; + +const InputWrapper = styled.div` + display: flex; + gap: 20px; +`; + +const Input = styled.input` + border: none; + border-bottom: 1px solid grey; + padding: 10px 20px; + outline: none; +`; + +const AddButton = styled.button` + width: 100px; + line-height: 30px; + border-radius: 25px; + border: none; + background-color: grey; + color: white; + cursor: pointer; +`; + +export default WithPeople; diff --git a/pages/create-post.tsx b/pages/create-post.tsx index 4212d8d7..01481697 100644 --- a/pages/create-post.tsx +++ b/pages/create-post.tsx @@ -1,5 +1,5 @@ import GNB from "@/Components/Layouts/GNB"; -import Post from "@/Components/Post/post"; +import Post from "@/Components/Post/Post"; import { NextPage, GetServerSideProps } from "next"; const CreatePostPage: NextPage = () => { diff --git a/yarn.lock b/yarn.lock index f25ea9e2..31ab31ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -409,6 +409,13 @@ dependencies: tslib "^2.4.0" +"@toast-ui/editor-plugin-color-syntax@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@toast-ui/editor-plugin-color-syntax/-/editor-plugin-color-syntax-3.1.0.tgz#afbaabe7fe315bf6b6c3d9a62564878d0a365549" + integrity sha512-UVKfMBPV+3snSaJn9RUKGbxJbgi92D2t68ow8wAjGezvMp1ht4UVETrvomdTGr+RYhXSeH3JvSwN9nmQqw0qzA== + dependencies: + tui-color-picker "^2.2.6" + "@toast-ui/editor@^3.2.1": version "3.2.1" resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-3.2.1.tgz#dcd0b7471299842b2962aab5d757723a61959f2a" @@ -1431,7 +1438,7 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.0.1: +eslint@8.33.0: version "8.33.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.33.0.tgz#02f110f32998cb598c6461f24f4d306e41ca33d7" integrity sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA== @@ -3040,6 +3047,11 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tui-color-picker@^2.2.6: + version "2.2.8" + resolved "https://registry.yarnpkg.com/tui-color-picker/-/tui-color-picker-2.2.8.tgz#8e140ab04066dbdb2353c4a1f434ad7d8d7b0d73" + integrity sha512-q5sE9NQ5NR9lYpilYjcI7Sdv0KCogo+W8fZY+AYTj/HYg+9fscYy3UuJ6UQiV1bF+ARCLwFRWC8UcOt9kuUctQ== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -3078,7 +3090,7 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@*: +typescript@4.9.5: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== From c7dd5a4724e5501668a4f67575fcf50adb82800d Mon Sep 17 00:00:00 2001 From: nno3onn Date: Wed, 15 Feb 2023 11:37:32 +0900 Subject: [PATCH 51/61] =?UTF-8?q?feat(PostPage):=20UI=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20=EC=99=84=EB=A3=8C=20-=20=ED=95=A8=EA=BB=98=ED=95=9C=20?= =?UTF-8?q?=EC=82=AC=EB=9E=8C=EB=93=A4=20=EA=B5=AC=ED=98=84=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20-=20info=20=EC=9E=85=EB=A0=A5=20=EB=B6=80=EB=B6=84?= =?UTF-8?q?=EB=93=A4=EA=B3=BC=20toast=20Editor=20=EB=B6=84=EB=A6=AC(input?= =?UTF-8?q?=20=EC=9E=85=EB=A0=A5=20=EC=8B=9C=20=EC=9E=90=EB=8F=99=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20toast=20Editor=EC=97=90=20focus=EB=90=98=EB=8A=94?= =?UTF-8?q?=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/Post/Post.tsx | 3 -- Components/Post/PostEditor.tsx | 2 +- Components/Post/WithPeople.tsx | 71 ++++++++++++++++++++++++++------- pages/create-post.tsx | 4 +- public/icons/close.png | Bin 0 -> 8350 bytes 5 files changed, 59 insertions(+), 21 deletions(-) create mode 100644 public/icons/close.png diff --git a/Components/Post/Post.tsx b/Components/Post/Post.tsx index 676339d9..90756179 100644 --- a/Components/Post/Post.tsx +++ b/Components/Post/Post.tsx @@ -75,9 +75,6 @@ const Post: NextPage = () => { setPeople={setPeople} />
-
- -
); }; diff --git a/Components/Post/PostEditor.tsx b/Components/Post/PostEditor.tsx index f7f2be41..9b44642b 100644 --- a/Components/Post/PostEditor.tsx +++ b/Components/Post/PostEditor.tsx @@ -1,9 +1,9 @@ -import "@toast-ui/editor/dist/toastui-editor.css"; // import "@toast-ui/editor/dist/theme/toastui-editor-dark.css"; // import "tui-color-picker/dist/tui-color-picker.css"; // import "@toast-ui/editor-plugin-color-syntax/dist/toastui-editor-plugin-color-syntax.css"; import { Editor } from "@toast-ui/react-editor"; import colorSyntax from "@toast-ui/editor-plugin-color-syntax"; +import "@toast-ui/editor/dist/toastui-editor.css"; const PostEditor = () => { const toolbarItems = [ diff --git a/Components/Post/WithPeople.tsx b/Components/Post/WithPeople.tsx index 2bec0724..aeb76895 100644 --- a/Components/Post/WithPeople.tsx +++ b/Components/Post/WithPeople.tsx @@ -1,4 +1,5 @@ -import { Dispatch, SetStateAction } from "react"; +import Image from "next/image"; +import { ChangeEvent, Dispatch, SetStateAction } from "react"; import styled from "styled-components"; export interface WithPersonType { @@ -14,25 +15,59 @@ interface WithPeopleProps { const WithPeople = ({ people, setPeople }: WithPeopleProps) => { const addPerson = () => { - setPeople((prev: WithPersonType) => - prev.push({ name: "", field: "", github: "" }) - ); + if (people.length === 0) { + setPeople([...people, { name: "", field: "", github: "" }]); + } else { + const lastPerson = people[people.length - 1]; + if (lastPerson.name && lastPerson.field && lastPerson.github) { + setPeople([...people, { name: "", field: "", github: "" }]); + } + } }; - const changeName = (idx: number) => {}; - const changeField = (idx: number) => {}; + const changePerson = + (idx: number, property: "name" | "field" | "github") => + ({ target: { value } }: ChangeEvent) => { + const newPeople = people.map((person, i) => { + if (i === idx) return { ...person, [property]: value }; + return person; + }); + setPeople(newPeople); + }; + + const onDelete = (idx: number) => () => { + const newPeople = people.filter((_, i) => i !== idx); + setPeople(newPeople); + }; - const changeGithub = (idx: number) => {}; return ( - {/* {people && - people.map((person, idx) => ( - - - - - - ))} */} + {people.map((person, idx) => ( + + + + + + + ))} + 참여자 추가 ); @@ -46,6 +81,7 @@ const WithPeopleContainer = styled.div` const InputWrapper = styled.div` display: flex; gap: 20px; + align-items: center; `; const Input = styled.input` @@ -65,4 +101,9 @@ const AddButton = styled.button` cursor: pointer; `; +const CancelButton = styled(Image)` + cursor: pointer; + padding: 0.125rem; +`; + export default WithPeople; diff --git a/pages/create-post.tsx b/pages/create-post.tsx index 01481697..fa755b6f 100644 --- a/pages/create-post.tsx +++ b/pages/create-post.tsx @@ -1,12 +1,12 @@ -import GNB from "@/Components/Layouts/GNB"; import Post from "@/Components/Post/Post"; +import PostEditor from "@/Components/Post/PostEditor"; import { NextPage, GetServerSideProps } from "next"; const CreatePostPage: NextPage = () => { return ( <> - + ); }; diff --git a/public/icons/close.png b/public/icons/close.png new file mode 100644 index 0000000000000000000000000000000000000000..a9413831d91aed81a7fe9944150e0985e935beb8 GIT binary patch literal 8350 zcmYLP3pmu-`#*zXyRfzkqNdHb6d}4OlhIZ*5nWwMOoVNTi89TSnQGfEZZ+gmn6|d; zE@D$+-KOnk5bfV?lH0TmYK0nw$(Z?{%jDPd^bFtk^ZA_jyyrdVyzh6M-RkK!bK1OV z0DzgyO&hiYpaFl>06J6Q$A_bTe}W%cG2bwE>cD^TI{VMS-@jmQ@{0jL-wFMv?6=t3 z3?CXD-spRHM^xxx&c5gnz~OLg4n&5>1n*;q*hEE#T^^**17IOwZdkYTXwE?A-ohg8 zzPa!EB0{g&HM(38th95`@NEB9v&@(AbXrly>^VhSF1>h=ns~$9e97+Ms{i}jeZ`8G zC$e^if4AbsykzeOw{ILjZvXdg4}FE@d}rm>?~gBjs=M{axl?VQ`88%cjOUb&boK9T z9)CY>=EeUyN6}h&KOyg9P54mE()^DnXnK2_6VvG9-{)mZhnWec;$Y^2>byXv?7`V) z9q^c)AwB+f%@D_|!d5(dtG~Lt{^qE&Q2MIvNSAh6{C_)7SFU_7RNbO=Uy!DnbGO7^ z=jjXGWiiaIZ0W&PRrNX`GRZZQ-)Gh=t?U|K&&-Rt$9VOM*>z#>&_pZk)tSD_9f<

J6-bF!@=UZT5#bnk6B&Oj%URP^E3y=udL0 zM|A7Y#bYLV`#IBVj!~K_7j`?n?4QcItc(zN-RO>4)mIxfs-vXUIEnKu64v=VxtvB1 z|7|)Dg~r1<2oj1rZG@X;dw1;RSFgG;TBy3pb*vQL)#5iCO^9U(S_ezl%QgsV9Ug8h z&yZ3ZB~t>H52ZFw0qjG8X;Oohq2CjGx3o<-pSZ>yo)PeO$nZ~Zol5~YeRN^v;J2f# zA;Z1Fd(TiW-Ak%S=xPBt?m%6P~G-APH8(Gewi?QT$>twY=q_qq}U_!Ld*u zh|GvK>tU|JR5L#VEIvYtXyY!O_=gfi@^?@s1kr&JkA0|EyXlHV9>xtls}17w}iS zZ&HaB-U0)2uY^VK;?n5D(XB_0Ebx$x7*aqun-|;N64>Qj=h2ZXt&CD=GcGEZWbc8# z_^!M=(cHXe)Zq0^TIv&tOHAV#Ckk+vmZ^${jhT5DXtlhlr?X>RlK|gro08MCO4!2> z)GI%vXD-h^Y642M^k`hiJbAa6N_Uri9N1wkY7kU83~GVKwh3leM(1cmgO_Eho(@iiv;saj4<8(h z91rY@DK?V_-Bi&R8jQT8b!SL}2Tp>BM$NX1wH#&U@Wax#N?l;{_!Z!{#I&paTflIa zwT&#E+k_q*YF9Zr2LqGSLS2xR=QU1k4r>-DHjmG?dU*(l4#UN`nVM_Hy?yN5ocE4E zG6o;ixIsiTM7)BC_vHhOWb`0)WU+T0R4j;T=dBs4$dI-%opYsrJ@*U$aw{EQOQ9a1 zYO(fpj0l?y1ay_PxG$|LKR)Y@EF16>cPLvvMO7%{fIwRGB&{$WK9!Ox)~aq1k{S2%u~T! zyMzs2NkJ`7!^IDZPmDd#?)&*ww4|>VM9UMPo*#GMZN+P@DLT6$9 zYQ`wfg101L_0wM+g0w*Y&k8T0g+P(LzQ(an{?e$5U-a-5U>)oj8In>L$R1W)ETySJ zr`iUEqaEd|J*04wpQV3vo3QQ4Zac=mG7(gkp>GOPwx?U%o<{HI7dNjP+#&$SmdvQHO=C9jnsr{IS@&*{ zbD{;ZZU>DuM$0t#-0jNToZE`gB)%t1dR9O>&*I|$j9ZntJ13ccKwGJ$YOU#&H0aiA zXlwlKGf{FI8LdAX9cMzH3n!U3t}C4UHpqvJD7i_76wz{sODWRj|T4Gwc;a+ra|D$kYMK8Jzr46!%rKZhZ2GaN=d zIm~=y{4B&T+M&#~R2ds$cT0BF*UswU>5^%exym_L6;bzbF!@C=2$m{MH82(fDJ1NL z7iB{mE{p)b{mZ~pE z+)8F+pauap<|2LJd7>W!BfL#HMQut(CIiB?cnB zN=$^sUV>P)fUrDZ&RkU(JRnZ}ioMrR10yhyMSv!WXyjr(amoifWfes9L$LldHEkQF z1*vIpF|I0BsV5D6f|H)P3@50>8?Jag?g^du_jeNAU)<2R-AI89kB%+Sk`>@{$FvSfy zpd%Vq~>E)|9&(OslVDtT>=SS!{x)KN*Pq4Fu(Lq(*9#$XCRncV2W)!!Gg=ip2W)aV zi6`knHbg!##SqqF%(5mdJ2O1|DKh+xD@dbcD*-OUk+;sl@@#n0!;!7XI{2T$`t>A; znLlCLc0${T_2H$A4kxw_)=wrW7KsyLUoZ*cFa}1X6QC&plCXW%(|t~+Eij}MB}K$( zVcfgfNWR^Kg8j&8fNQjWkEsh5U6k8O!Qq& zVUsHvdKdC)Sj}ogNB1TU8QIPXnR3-mS)(<}iB+4zktyGZjAe~jb+^@%-iX#LJCp!R zHX-2S`D)-L1U#f3xd7b^(RbAPzoAL{N2+O?5zWAu&@ zBhdJ8Ewk&Abj83)(GOj@(vQpq;Z&^|p!b0e>q$DJGzi$Oas}Z(E3)Tn@>kny_`>to z8nQ0xi{@GKLK^_9DG6kF$Q{C`f|xL^k`493HV5FVVTuZC>k|~wc0-Ewaaq{186X2n zHl;HXgFwl0R}k~F!p}sLZ)UHN1tk|50c$8}V#%8eCB;eL5(I{VlEbcGX1(wsRMa%( z@7S&^go?WjDLE%(VJl{UXHao-y>Qnu;A?EkUu?-gi`Uko|S_4XST=^!Z z^;FjJBv7$Aogq45M2XIZxH)zj(nZ^p0Nz@4U!%|cT6F_g6%_AAo%6%+bEQbo z`9SB(9=(!nuA(yZTcghN&~yfH6+MEOv1z6(W5}f^>z52#@<60m$2SaG;jL3>RZr!g zG@|sMk!ef*OyY;Q$u-#rTt)U!q}<+=6&&U+;#g;1WV;vxQovwnF3Scj< z=lLzu0Oj^QwT%$&e@PY?3*j~%@?uz90_`2j{&V_3G=H(`$RkM0NLT$4tOeddnlYq} zP3x&Gf;3B2GPFLo>!}?uq(r=c`FBOCq`~G~HnQ%QPriaybNME@2|Ic!*z>cZ;)1@& z+z3P@%lhc9;Bqi1F{>B0FVlEFTN4#rCV%R%9AO>#Qp@qVq6%~MeomVH8B^q(OpgjeNeS5N>`Zf?DB2V~EL z?5)Zifxc*oA+XMs<=@j`y@$E!A#Z`?Z>IwH>xyicYY**#@1maO9GJZVis=6=dA)Ty ztV0mELGBRd3Q!Wyt{0j?#ThV(w<@jA>WdZ`0$8qvolOFv&2V3&Gu%V9?9jfruJD7B zZT29`w5R!!A*B&Yc3ASBLCILS)i%gWLtO#dY6kVfrFI%w$)#xLYBCq3$QXCr1PcH0 zFO7#?1i}hsF}NJd6Tmk0R?hNNTE!~y+P3845pG!qd`oixtVGqWEvmR@nS$puSnNLO zsSVRQ3|IIvyj?4HO%}~l;XyvQ^K;Q$5(ImP^`Glv;0Gh5^IE7ls_hiafQPa z{m%&RliQQbbI=yE__GU^(AHS=nJD=I87KX7q(J{VCYk2&{`K2D83rwgb+`H~mu~DUKLF$I^Q|ya<3&NDDYl~F6~rxo3jzqUXdz`bpg?M^U$s23arl|eJ^y? zKhWWCM7O)Dg;Wx(XITF>(a*wF%#hlItNL0s%MY`-#B>Gs0(}pO;56iv&;r+Rz>}Cr zNzPBhtPr)}b~Nc)YvPp0H^}=;G10h&qZ2}^7KtVHem-%k92PNWWq}4n-)1ACwW?{; zQT?boqNXjx`ZI}sM+Ta7R3f}#Ve8R{^$(KhNET!LcA~%Os$$PJCC$~v3WmxU*UTNH za%EjZI3X-HP$w3Vgal)ph`ceb)!;dYV#?~lz(g`n-^Iw`K6@hXjhoSmY1n=KMHCQT z$~{7RiD|*aD_=`Q3!6str{j*ugUpllH3q^X5WNq`T8;J7iGC;!_yM)a2$}NLEOX3S zO-z=!ZGe>la`?&y6vb>);?yi+YQ!eV2F!woBOWUYO}Z3D2PM)hT&`!3=t$}akObcm zuTt1d;?zxCuKUd*`tB(B=)gonOHN?g3N`IK)>k*h99&OEkQ!aI6xXYJNE^tWg`?A; z*2f;(Y3zpKSczMwUF&Q7rrRDs@V5E z0lvk+oD>YS+k=7mM87cw>90>ECSzAc1D)aPg++TN*Kj!-0StnN)Z&cSHZ z{iv?KIk@FGuCBg+LgL_^?ea-uA1h! z649opX*aO`6}A4~7-&cI9p@mRQ7X~*L}%OnAJzJEu_>9DULaPenw2#jnf_JR{gKEt zO--smPOW~aHVq<^r<&!94vGt3s9OSew9xkVbjlgx)1mMFEz58dbi|2TwONsa4TEvM zexv_k-?TGx;M6!`dLiqb8s;?CXVhgn659a;5i@88}@7~?n zJ$i+?`s`2iJn3cKu@^M>7G7G7UadmqB0CLF;iyFgeD}Gf%kkv>NVKZ+OeG)WR-8{) zt1QL&VeF?x544s1BH2ArOK)1+gs;jcr}M)U`DJDv)$?U1Ge9VHfUnMH$D51$1y$FM zolicxE|xRad?c!BoUyB8MEm)BN6BINenH=$ts-;5(Bl`{l&s^;@LQ+Y zZsY7{(*^M=uIk}LLM?eevz@W~^o*bQ`Z@{6bW z{9DEl<#J8f^Ss_D0zG&a3Rl1w`X@P2T6zrxoq=Dyt9t8fG?ui!W{H2D(ruz@Si3wc zPEfT%9R5Pv?2#!QGBr&&oe6~I3?aPIP4pFA_} zFUQVZJk(B=9Cgl=dOgx{EIU1e|7yDuJPy+`>0TektSN(lca2om8s}MTe_Q8z4mf3BL;n9iKhDr;Oo}`k3M~ z+*V2x9ux*0hv9oY>?n~r$7M)c+w*-5?@my9@4w&uTokq{F+3gd_d2Rw?NxuP?IT3exvGq5YuGJ9ITX1nJW1($ds`^O)Tq+ zUoY@?mz^~-2~B|wQp0|&jy1wf(F1Qk@y6QR10*Y;r>qL->7CQ1{Ysj6^m^^4-q}M6 z%Cmd9{QSPS$SRj+@!(_27pE_+hrQk(h7_;f-)YS?a*c@wBa^~hl=;J_D6IE`PX^=S zE5lyM4f^)xbgw#j@=imy6OaEf+F~L1pCX&4cKAIN?8J7K(KQl2#TxV;ad2c^Q*^>4 zN-1*I9V>I%o28)i%H zExT~K>`_0DHNJ7L`OrC-ye5NP)}t|Oul=oUZXYuRijf%s9UEoBTjPl-K(Z+BqO|*Z zcd&ujAWhM;*v3_$ctfjQebRutN$F?v9;SEs;7uCiQi5>40B(=_%QIgxYn{a74YnU* zcs&QTkH*#j*+-BVAfxe(Vm2Xmcp7ysyaq5I3aB3}6g2RF{UC%iEdCKu;c} zCQBM70`d;y$b-_zQ5j(SnyR)PPUL)TD$w*#ir?KR&w47n1 zdh@pHZOzxS6g%7R1gnm(s&EqDrE#|iqMi(DesAmijyLWb%bB%+DNCU-E=$v9!SA|K zdJ0P8W+`6KialjBS1U6An)psI8Zv4y_On>y2lxjAdgyNfsvN|&`&U_-zgJOQwrk%s T?fbSHngDa7=Z2f#uul9x0v3b9 literal 0 HcmV?d00001 From b6573d26b627b05711eef2a937b902f08e6239cb Mon Sep 17 00:00:00 2001 From: hyoloui Date: Wed, 15 Feb 2023 12:54:45 +0900 Subject: [PATCH 52/61] =?UTF-8?q?feat(PostEditor):=20=EB=B7=B0=EC=96=B4=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=95=95=EC=B6=95,=20=EB=B3=B4?= =?UTF-8?q?=EC=9D=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - imageCompression 라이브러리 사용하여 이미지 압축 - Editor hook 커스텀 - supabase 스토리지에 이미지 서버통신 성공 #5 #41 by @arch-spatula @hyoloui --- Components/Post/PostEditor.tsx | 83 ++++++++++++++++++++++++++++++++-- package.json | 1 + 2 files changed, 79 insertions(+), 5 deletions(-) diff --git a/Components/Post/PostEditor.tsx b/Components/Post/PostEditor.tsx index f7f2be41..5835e3f3 100644 --- a/Components/Post/PostEditor.tsx +++ b/Components/Post/PostEditor.tsx @@ -1,11 +1,22 @@ import "@toast-ui/editor/dist/toastui-editor.css"; -// import "@toast-ui/editor/dist/theme/toastui-editor-dark.css"; -// import "tui-color-picker/dist/tui-color-picker.css"; -// import "@toast-ui/editor-plugin-color-syntax/dist/toastui-editor-plugin-color-syntax.css"; +import "@toast-ui/editor/dist/theme/toastui-editor-dark.css"; +import "tui-color-picker/dist/tui-color-picker.css"; +import "@toast-ui/editor-plugin-color-syntax/dist/toastui-editor-plugin-color-syntax.css"; +import "@toast-ui/editor/dist/i18n/ko-kr"; + import { Editor } from "@toast-ui/react-editor"; import colorSyntax from "@toast-ui/editor-plugin-color-syntax"; +import { useEffect, useRef } from "react"; +import supabase from "@/lib/supabase"; +import imageCompression from "browser-image-compression"; +/** + * @TODO storage 삭제 구현 필요 + * @TODO uuid flag 꽃아야 함 >> 게시와 임시저장의 용도로 분류 + */ const PostEditor = () => { + const editorRef = useRef(null); + const toolbarItems = [ ["heading", "bold", "italic", "strike"], ["hr"], @@ -15,14 +26,73 @@ const PostEditor = () => { ["code"], ["scrollSync"], ]; + + useEffect(() => { + const editorIns = editorRef.current.getInstance(); + editorIns.removeHook("addImageBlobHook"); + editorIns.addHook("addImageBlobHook", addImage); + }, []); + + // ------------- image Function ------------- // 에디터에 이미지 추가 + + const addImage = async (blob, dropImage) => { + // https://www.youtube.com/watch?v=dLqSmxX3r7I + const img = await compressImg(blob); // 이미지 압축 + const url = await uploadImage(img); // 업로드된 이미지 서버 url + dropImage(url, "alt_text"); // 에디터에 이미지 추가 + }; + + // 이미지 업로드 + + const uploadImage = async (blob) => { + try { + // firebase Storage Create Reference 파일 경로 / 파일 명 . 확장자 + const imgPath = crypto.randomUUID(); + await supabase.storage.from("post-image").upload(imgPath, blob); + + const { data, error } = await supabase.storage.getBucket("post-image"); + + // 이미지 올리기 + const urlResult = await supabase.storage + .from("post-image") + .getPublicUrl(imgPath); + return urlResult.data.publicUrl; + } catch (error) { + console.log(error); + return false; + } + }; + + // //이미지 압축 + const compressImg = async (blob: File): Promise => { + const options = { + maxSize: 1, + initialQuality: 0.55, // initial 0.7 + }; + const result = await imageCompression(blob, options) + .then((res) => res) + .catch((e) => console.log(e, "압축 에러")); + return result; + }; + + // detail에 활용 가능 + // const getContent = () => { + // //글 내용 HTML 문자열로 불러오기 + // const editorIns = editorRef.current.getInstance(); + // return editorIns.getHTML(); + // }; + return ( { // preset: ["#1F2E3D", "#4c5864", "#ED7675"], // }, ]} + hooks={{ + addImageBlobHook: addImage, + }} /> ); }; diff --git a/package.json b/package.json index eba076b9..30834ebf 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@toast-ui/editor-plugin-color-syntax": "^3.1.0", "@toast-ui/react-editor": "^3.2.2", "axios": "^1.3.2", + "browser-image-compression": "^2.0.0", "eslint": "8.33.0", "eslint-config-next": "13.1.6", "lodash": "^4.17.21", From 93c71192c507d20791c403cce4e79f56628e6326 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Wed, 15 Feb 2023 12:58:18 +0900 Subject: [PATCH 53/61] =?UTF-8?q?fix(FiledDropDown):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=ED=81=B4=EB=A6=AD=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cursor 예약어로 인한 에러 해결 #5 by @arch-spatula --- Components/Post/FieldDropDown.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Components/Post/FieldDropDown.tsx b/Components/Post/FieldDropDown.tsx index e600d0d9..943695f6 100644 --- a/Components/Post/FieldDropDown.tsx +++ b/Components/Post/FieldDropDown.tsx @@ -86,7 +86,7 @@ const FieldDropDown = ({ setSelectedItem }: FieldDropDownProps) => { handleOverlayItem(item)} - cursor + dataCursor={true} > {item} @@ -112,11 +112,11 @@ const FiledItemContainer = styled.li<{ key?: string; onMouseOver?: () => void; onClick?: () => void; - cursor?: boolean; + dataCursor?: boolean; }>` padding: 0.75rem; width: 8.75rem; - ${(props) => props.cursor && "cursor: pointer;"}; + ${(props) => props.dataCursor && "cursor: pointer;"}; :hover { background: #e6e6e6; } From 3007884e4cbd43394fc875485dd3e3d2bf2016db Mon Sep 17 00:00:00 2001 From: hyoloui Date: Wed, 15 Feb 2023 14:35:23 +0900 Subject: [PATCH 54/61] =?UTF-8?q?fix(post):=20self=20is=20not=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - dynamic route 정상 작동 #5 #41 --- Components/Post/Post.tsx | 1 + pages/create-post.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Components/Post/Post.tsx b/Components/Post/Post.tsx index 90756179..d570fbfa 100644 --- a/Components/Post/Post.tsx +++ b/Components/Post/Post.tsx @@ -75,6 +75,7 @@ const Post: NextPage = () => { setPeople={setPeople} /> + ); }; diff --git a/pages/create-post.tsx b/pages/create-post.tsx index fa755b6f..01481697 100644 --- a/pages/create-post.tsx +++ b/pages/create-post.tsx @@ -1,12 +1,12 @@ +import GNB from "@/Components/Layouts/GNB"; import Post from "@/Components/Post/Post"; -import PostEditor from "@/Components/Post/PostEditor"; import { NextPage, GetServerSideProps } from "next"; const CreatePostPage: NextPage = () => { return ( <> + - ); }; From f912296263a05633a8d5fc5f223339596922ae4a Mon Sep 17 00:00:00 2001 From: hyoloui Date: Wed, 15 Feb 2023 15:22:43 +0900 Subject: [PATCH 55/61] =?UTF-8?q?feat(PostEditor):=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=B7=A8=EB=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - useRef.current.getinstance() #5 #41 --- Components/Post/PostEditor.tsx | 70 +++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/Components/Post/PostEditor.tsx b/Components/Post/PostEditor.tsx index 5835e3f3..d4ebb1c6 100644 --- a/Components/Post/PostEditor.tsx +++ b/Components/Post/PostEditor.tsx @@ -6,7 +6,7 @@ import "@toast-ui/editor/dist/i18n/ko-kr"; import { Editor } from "@toast-ui/react-editor"; import colorSyntax from "@toast-ui/editor-plugin-color-syntax"; -import { useEffect, useRef } from "react"; +import { LegacyRef, useEffect, useRef } from "react"; import supabase from "@/lib/supabase"; import imageCompression from "browser-image-compression"; @@ -82,28 +82,54 @@ const PostEditor = () => { // return editorIns.getHTML(); // }; + const handleRegisterButton = () => { + // 입력창에 입력한 내용을 HTML 태그 형태로 취득 + console.log(editorRef.current?.getInstance().getHTML()); + // 입력창에 입력한 내용을 MarkDown 형태로 취득 + console.log(editorRef.current?.getInstance().getMarkdown()); + }; + + // 진행 해야 함 + // const getMarkDown = () => { + // //글 내용 마크다운 문자열로 불러오기 + // const editorIns = editorRef.current.getInstance(); + // return editorIns.getMarkdown(); + // }; + + // const validation_check = () => { + // const title = titleRef.current.value.trim(); + // const content = getMarkDown(); + // if (title !== "" || content !== "") { + // // DB에 저장 + // } else { + // // 에러 표시 + // } + // }; return ( - + <> + + + ); }; From b7fd9ce06d3bd91057b165a4e9bbf267f706a457 Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Wed, 15 Feb 2023 15:45:03 +0900 Subject: [PATCH 56/61] =?UTF-8?q?feat(Post,=20Editor):=20state=EC=99=80=20?= =?UTF-8?q?Page=EB=A1=9C=20=EC=A4=91=EC=95=99=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - state추가 - post에 state 중앙화 #5 #41 --- Components/Post/Post.tsx | 5 ++- Components/Post/PostEditor.tsx | 72 ++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/Components/Post/Post.tsx b/Components/Post/Post.tsx index d570fbfa..cfc8219b 100644 --- a/Components/Post/Post.tsx +++ b/Components/Post/Post.tsx @@ -31,7 +31,10 @@ const Post: NextPage = () => { const [isPublic, setIsPublic] = useState(false); const [people, setPeople] = useState([]); + const [postContent, setPostContent] = useState(""); + const onClickTest = () => { + // 저장하기 console.log("hi"); }; @@ -75,7 +78,7 @@ const Post: NextPage = () => { setPeople={setPeople} /> - + ); }; diff --git a/Components/Post/PostEditor.tsx b/Components/Post/PostEditor.tsx index d4ebb1c6..9e5d4af9 100644 --- a/Components/Post/PostEditor.tsx +++ b/Components/Post/PostEditor.tsx @@ -6,7 +6,7 @@ import "@toast-ui/editor/dist/i18n/ko-kr"; import { Editor } from "@toast-ui/react-editor"; import colorSyntax from "@toast-ui/editor-plugin-color-syntax"; -import { LegacyRef, useEffect, useRef } from "react"; +import { Dispatch, SetStateAction, useEffect, useRef } from "react"; import supabase from "@/lib/supabase"; import imageCompression from "browser-image-compression"; @@ -14,7 +14,13 @@ import imageCompression from "browser-image-compression"; * @TODO storage 삭제 구현 필요 * @TODO uuid flag 꽃아야 함 >> 게시와 임시저장의 용도로 분류 */ -const PostEditor = () => { + +interface PostEditorProps { + postContent: string; + setPostContent: Dispatch>; +} + +const PostEditor = ({ postContent, setPostContent }: PostEditorProps) => { const editorRef = useRef(null); const toolbarItems = [ @@ -35,7 +41,7 @@ const PostEditor = () => { // ------------- image Function ------------- // 에디터에 이미지 추가 - const addImage = async (blob, dropImage) => { + const addImage = async (blob: File, dropImage) => { // https://www.youtube.com/watch?v=dLqSmxX3r7I const img = await compressImg(blob); // 이미지 압축 const url = await uploadImage(img); // 업로드된 이미지 서버 url @@ -44,14 +50,12 @@ const PostEditor = () => { // 이미지 업로드 - const uploadImage = async (blob) => { + const uploadImage = async (blob: File) => { try { // firebase Storage Create Reference 파일 경로 / 파일 명 . 확장자 const imgPath = crypto.randomUUID(); await supabase.storage.from("post-image").upload(imgPath, blob); - const { data, error } = await supabase.storage.getBucket("post-image"); - // 이미지 올리기 const urlResult = await supabase.storage .from("post-image") @@ -83,10 +87,13 @@ const PostEditor = () => { // }; const handleRegisterButton = () => { - // 입력창에 입력한 내용을 HTML 태그 형태로 취득 - console.log(editorRef.current?.getInstance().getHTML()); - // 입력창에 입력한 내용을 MarkDown 형태로 취득 - console.log(editorRef.current?.getInstance().getMarkdown()); + // 유효성 검사 + const editorText = editorRef.current?.getInstance().getMarkdown(); + if ((editorText === " ") | (editorText === "")) { + return; + } + // HTML 대신에 Markdown으로 저장합니다. + setPostContent(editorText); }; // 진행 해야 함 @@ -106,30 +113,27 @@ const PostEditor = () => { // } // }; return ( - <> - - - + ); }; From 3828f46d24a904a61ad012d2751fa5c23da2d037 Mon Sep 17 00:00:00 2001 From: hyoloui Date: Wed, 15 Feb 2023 17:20:27 +0900 Subject: [PATCH 57/61] =?UTF-8?q?feat(Post,=20PostEditor):=20supabase=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84=20=ED=86=B5=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페어 작업중 페어 변경 #5 #41 --- Components/Post/Post.tsx | 64 +++++++++++++++++++++++++++------- Components/Post/PostEditor.tsx | 14 ++++---- types.d.ts | 16 +++++---- 3 files changed, 69 insertions(+), 25 deletions(-) diff --git a/Components/Post/Post.tsx b/Components/Post/Post.tsx index cfc8219b..d0c0dc76 100644 --- a/Components/Post/Post.tsx +++ b/Components/Post/Post.tsx @@ -3,9 +3,11 @@ import styled from "styled-components"; import DefaultButton from "@/Components/Common/DefaultButton"; import PostTitle from "@/Components/Post/PostTitle"; import ProjectInfo from "@/Components/Post/ProjectInfo"; -import { useState } from "react"; +import { useRef, useState } from "react"; import dynamic from "next/dynamic"; import { WithPersonType } from "./WithPeople"; +import supabase from "@/lib/supabase"; +import { PostType } from "@/types"; /** * @TODO 코드블럭 @@ -17,7 +19,7 @@ import { WithPersonType } from "./WithPeople"; * @TODO 카테고리 중복 선택 , 보여주는 UI * @TODO 서버통신 연결 */ - +const id = crypto.randomUUID(); const Post: NextPage = () => { const [title, setTitle] = useState(""); const [subTitle, setSubTitle] = useState(""); @@ -33,11 +35,48 @@ const Post: NextPage = () => { const [postContent, setPostContent] = useState(""); - const onClickTest = () => { - // 저장하기 - console.log("hi"); + const editorRef = useRef(null); + const editorText = editorRef.current?.getInstance().getMarkdown(); + + enum Field { + WEB = "웹", + APP = "앱", + SOFTWARE = "소프트웨어", + DATA = "데이터", + WEB3 = "블록체인", + DEVOPS = "데브옵스", + IOT_AND_EMBEDDED = "IOT,임베디드", + SECURITY = "보안", + } + const postRow = { + id, + user_id: id, + title, + sub_title: subTitle, + content: postContent, + thumbnail: imgFile, + created_at: new Date(), + progress_date: [String(startDate), String(endDate)], + github_url: "https://github.com/", + url: "https://naver.com/", + is_public: isPublic, + tag, + members: people, + skills: techStack, + large_category: Field.WEB, + sub_category: "프론트엔드", }; + const onSave = () => { + // 저장 버튼 + setPostContent(editorText); + }; + const onPost = async () => { + // 게시 버튼 + setPostContent(editorText); + await supabase.from("post").insert(postRow); + }; + console.log(postContent); const PostEditor = dynamic(() => import("./PostEditor"), { ssr: false, }); @@ -46,13 +85,8 @@ const Post: NextPage = () => { 글이 저장 되었습니다. - - + +

{ setPeople={setPeople} />
- + ); }; diff --git a/Components/Post/PostEditor.tsx b/Components/Post/PostEditor.tsx index 9e5d4af9..eb4f28ac 100644 --- a/Components/Post/PostEditor.tsx +++ b/Components/Post/PostEditor.tsx @@ -6,7 +6,7 @@ import "@toast-ui/editor/dist/i18n/ko-kr"; import { Editor } from "@toast-ui/react-editor"; import colorSyntax from "@toast-ui/editor-plugin-color-syntax"; -import { Dispatch, SetStateAction, useEffect, useRef } from "react"; +import { Dispatch, LegacyRef, SetStateAction, useEffect, useRef } from "react"; import supabase from "@/lib/supabase"; import imageCompression from "browser-image-compression"; @@ -18,11 +18,14 @@ import imageCompression from "browser-image-compression"; interface PostEditorProps { postContent: string; setPostContent: Dispatch>; + editorRef: LegacyRef; } -const PostEditor = ({ postContent, setPostContent }: PostEditorProps) => { - const editorRef = useRef(null); - +const PostEditor = ({ + postContent, + setPostContent, + editorRef, +}: PostEditorProps) => { const toolbarItems = [ ["heading", "bold", "italic", "strike"], ["hr"], @@ -45,14 +48,13 @@ const PostEditor = ({ postContent, setPostContent }: PostEditorProps) => { // https://www.youtube.com/watch?v=dLqSmxX3r7I const img = await compressImg(blob); // 이미지 압축 const url = await uploadImage(img); // 업로드된 이미지 서버 url - dropImage(url, "alt_text"); // 에디터에 이미지 추가 + dropImage(url, `${blob.name}`); // 에디터에 이미지 추가 }; // 이미지 업로드 const uploadImage = async (blob: File) => { try { - // firebase Storage Create Reference 파일 경로 / 파일 명 . 확장자 const imgPath = crypto.randomUUID(); await supabase.storage.from("post-image").upload(imgPath, blob); diff --git a/types.d.ts b/types.d.ts index a2534faa..343da65d 100644 --- a/types.d.ts +++ b/types.d.ts @@ -1,6 +1,8 @@ +import { WithPersonType } from "./Components/Post/WithPeople"; + type Gender = "남자" | "여자" | "선택안함"; -enum Field { +declare enum Field { WEB = "웹", APP = "앱", SOFTWARE = "소프트웨어", @@ -84,22 +86,24 @@ interface NotificationType { target_id: string; } -interface PostType { +declare interface PostType { id: string; user_id: string; title: string; + sub_title: string; content: string; thumbnail: string; - large_category: Field; - sub_category: SubCategory; - created_at: Date; progress_date: [string, string]; github_url: string; url: string; is_public: boolean; + members: WithPersonType[]; skills: string[]; - members: string[]; tag: string[]; + created_at: Date; + large_category: FiledType; + sub_category: SubCategory; + // } interface FollowType { From c1c859ce1f2409e6a5173883262796b12f332c2b Mon Sep 17 00:00:00 2001 From: nno3onn Date: Wed, 15 Feb 2023 17:38:18 +0900 Subject: [PATCH 58/61] =?UTF-8?q?fix:=20px=20->=20rem=20=ED=8F=B0=ED=8A=B8?= =?UTF-8?q?=20=EC=82=AC=EC=9D=B4=EC=A6=88=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/Post/ProjectInfoDropDown.tsx | 6 +++--- Components/Post/WithPeople.tsx | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Components/Post/ProjectInfoDropDown.tsx b/Components/Post/ProjectInfoDropDown.tsx index 897eca32..e29561ed 100644 --- a/Components/Post/ProjectInfoDropDown.tsx +++ b/Components/Post/ProjectInfoDropDown.tsx @@ -130,7 +130,7 @@ const ProjectInfoDropDown = ({ const ProjectInfoDropDownContainer = styled.div` height: 12.5rem; - margin-top: 2px; + margin-top: 0.125rem; border: 1px solid #cccccc; display: grid; @@ -169,11 +169,11 @@ const DatePickerContainer = styled.div` const ToggleWrapper = styled.div` display: flex; - gap: 12px; + gap: 0.75rem; align-items: center; p { color: #999999; - font-size: 13px; + font-size: 0.8125rem; } `; diff --git a/Components/Post/WithPeople.tsx b/Components/Post/WithPeople.tsx index aeb76895..326a1b32 100644 --- a/Components/Post/WithPeople.tsx +++ b/Components/Post/WithPeople.tsx @@ -80,21 +80,21 @@ const WithPeopleContainer = styled.div` const InputWrapper = styled.div` display: flex; - gap: 20px; + gap: 1.25rem; align-items: center; `; const Input = styled.input` border: none; - border-bottom: 1px solid grey; - padding: 10px 20px; + border-bottom: 0.0625rem solid grey; + padding: 0.625rem 1.25rem; outline: none; `; const AddButton = styled.button` - width: 100px; - line-height: 30px; - border-radius: 25px; + width: 6.25rem; + line-height: 1.875rem; + border-radius: 1.5625rem; border: none; background-color: grey; color: white; From dd03a46bfc483d1906465b2512d0b846faadba38 Mon Sep 17 00:00:00 2001 From: Jeremy-kr Date: Wed, 15 Feb 2023 21:34:37 +0900 Subject: [PATCH 59/61] =?UTF-8?q?feat:=20post=20create=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #5 --- .eslintrc.json | 3 +- Components/Post/FieldDropDown.tsx | 32 +++--- Components/Post/Post.tsx | 146 +++++++++++------------- Components/Post/PostEditor.tsx | 43 ++++--- Components/Post/PostTitle.tsx | 77 +++++-------- Components/Post/ProjectInfo.tsx | 50 +------- Components/Post/ProjectInfoDropDown.tsx | 107 ++++++++--------- Components/Post/WithPeople.tsx | 16 +-- lib/recoil/index.ts | 29 ++++- lib/recoil/postAtoms.ts | 77 +++++++++++++ pages/create-post.tsx | 12 +- types.d.ts | 22 ++-- utils/commons/getYYYYMM.ts | 7 ++ yarn.lock | 40 ++++++- 14 files changed, 359 insertions(+), 302 deletions(-) create mode 100644 lib/recoil/postAtoms.ts create mode 100644 utils/commons/getYYYYMM.ts diff --git a/.eslintrc.json b/.eslintrc.json index b81a77f9..5c053f2d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -32,6 +32,7 @@ { "namedComponents": "arrow-function" } ], // no-extraneous-dependencies 오류가 발생해 임시로 해제 - "import/no-extraneous-dependencies": 0 + "import/no-extraneous-dependencies": 0, + "@typescript-eslint/ban-ts-comment": 0 } } diff --git a/Components/Post/FieldDropDown.tsx b/Components/Post/FieldDropDown.tsx index 943695f6..596ab5dc 100644 --- a/Components/Post/FieldDropDown.tsx +++ b/Components/Post/FieldDropDown.tsx @@ -1,10 +1,6 @@ -import { - Dispatch, - SetStateAction, - useEffect, - useReducer, - useState, -} from "react"; +import { postLargeCategory, postSubCategory } from "@/lib/recoil"; +import { useReducer } from "react"; +import { useSetRecoilState } from "recoil"; import styled from "styled-components"; /** @@ -54,18 +50,19 @@ const reducer = (_state: string[], action: { type: Field }): string[] => { return ["기타"]; } }; -interface FieldDropDownProps { - setSelectedItem: Dispatch>; -} -const FieldDropDown = ({ setSelectedItem }: FieldDropDownProps) => { + +const FieldDropDown = () => { const [state, dispatch] = useReducer(reducer, initialState); + const setLargeCategory = useSetRecoilState(postLargeCategory); + const setSubCategory = useSetRecoilState(postSubCategory); + const handleLargeCategory = (item: Field) => { dispatch({ type: item }); }; - const handleOverlayItem = (item: string) => { - setSelectedItem(item); + const handleClickSubCategory = (item: string) => { + setSubCategory(item); }; return ( @@ -73,7 +70,10 @@ const FieldDropDown = ({ setSelectedItem }: FieldDropDownProps) => {
    {field.map((item) => ( handleLargeCategory(item)} + onMouseOver={() => { + handleLargeCategory(item); + setLargeCategory(item); + }} key={item.toString()} > {item} @@ -85,8 +85,8 @@ const FieldDropDown = ({ setSelectedItem }: FieldDropDownProps) => { {state.map((item) => ( handleOverlayItem(item)} - dataCursor={true} + onClick={() => handleClickSubCategory(item)} + dataCursor > {item} diff --git a/Components/Post/Post.tsx b/Components/Post/Post.tsx index d0c0dc76..4664fc41 100644 --- a/Components/Post/Post.tsx +++ b/Components/Post/Post.tsx @@ -3,11 +3,23 @@ import styled from "styled-components"; import DefaultButton from "@/Components/Common/DefaultButton"; import PostTitle from "@/Components/Post/PostTitle"; import ProjectInfo from "@/Components/Post/ProjectInfo"; -import { useRef, useState } from "react"; -import dynamic from "next/dynamic"; -import { WithPersonType } from "./WithPeople"; +import { useRecoilValue } from "recoil"; +import { + postContent, + postLargeCategory as recoilPostLargeCategory, + postMembers, + postProjectDuration, + postPublic, + postSkills, + postSubCategory as recoilPostSubCategory, + postSubTitle, + postTags, + postTitle, + postTitleBackgroundColor, +} from "@/lib/recoil"; import supabase from "@/lib/supabase"; -import { PostType } from "@/types"; +import { useEffect, useState } from "react"; +import { useRouter } from "next/router"; /** * @TODO 코드블럭 @@ -19,104 +31,70 @@ import { PostType } from "@/types"; * @TODO 카테고리 중복 선택 , 보여주는 UI * @TODO 서버통신 연결 */ -const id = crypto.randomUUID(); const Post: NextPage = () => { - const [title, setTitle] = useState(""); - const [subTitle, setSubTitle] = useState(""); - const [imgFile, setImgFile] = useState(""); + const title = useRecoilValue(postTitle); + const subTitle = useRecoilValue(postSubTitle); + const titleBackgroundColor = useRecoilValue(postTitleBackgroundColor); + const [startDate, endDate] = useRecoilValue(postProjectDuration); + const skills = useRecoilValue(postSkills); + const tag = useRecoilValue(postTags); + const isPublic = useRecoilValue(postPublic); + const members = useRecoilValue(postMembers); + const content = useRecoilValue(postContent); + const postLargeCategory = useRecoilValue(recoilPostLargeCategory); + const postSubCategory = useRecoilValue(recoilPostSubCategory); - const [startDate, setStartDate] = useState(new Date()); - const [endDate, setEndDate] = useState(new Date()); + const router = useRouter(); - const [techStack, setTechStack] = useState([]); - const [tag, setTag] = useState([]); - const [isPublic, setIsPublic] = useState(false); - const [people, setPeople] = useState([]); - - const [postContent, setPostContent] = useState(""); - - const editorRef = useRef(null); - const editorText = editorRef.current?.getInstance().getMarkdown(); - - enum Field { - WEB = "웹", - APP = "앱", - SOFTWARE = "소프트웨어", - DATA = "데이터", - WEB3 = "블록체인", - DEVOPS = "데브옵스", - IOT_AND_EMBEDDED = "IOT,임베디드", - SECURITY = "보안", - } - const postRow = { - id, - user_id: id, + const newPostRow = { title, sub_title: subTitle, - content: postContent, - thumbnail: imgFile, - created_at: new Date(), - progress_date: [String(startDate), String(endDate)], - github_url: "https://github.com/", - url: "https://naver.com/", - is_public: isPublic, + title_background_color: titleBackgroundColor, + large_category: postLargeCategory, + sub_category: postSubCategory, + skills, + progress_date: [startDate, endDate], + members, tag, - members: people, - skills: techStack, - large_category: Field.WEB, - sub_category: "프론트엔드", + is_public: isPublic, + content, }; + const [isSaved, setIsSaved] = useState(false); + const onSave = () => { // 저장 버튼 - setPostContent(editorText); + setIsSaved(true); + setTimeout(() => { + setIsSaved(false); + }, 2000); }; const onPost = async () => { // 게시 버튼 - setPostContent(editorText); - await supabase.from("post").insert(postRow); + const { data, error } = await supabase + .from("post") + .insert(newPostRow) + .select() + .single(); + if (!error) { + router.push({ + pathname: "/", + query: { id: data.id }, + }); + } }; - console.log(postContent); - const PostEditor = dynamic(() => import("./PostEditor"), { - ssr: false, - }); return ( - 글이 저장 되었습니다. + 글이 저장 되었습니다.
    - - + +
    -
    ); }; @@ -133,6 +111,14 @@ const PostHeader = styled.section` padding: 2.8125rem 0; gap: 1.25rem; `; -const SaveAlert = styled.span``; + +interface SaveAlertProps { + isSaved: boolean; +} + +const SaveAlert = styled.span` + opacity: ${({ isSaved }) => (isSaved ? 1 : 0)}; + transition: all 0.5s ease-in-out; +`; export default Post; diff --git a/Components/Post/PostEditor.tsx b/Components/Post/PostEditor.tsx index eb4f28ac..7d665ec2 100644 --- a/Components/Post/PostEditor.tsx +++ b/Components/Post/PostEditor.tsx @@ -6,9 +6,11 @@ import "@toast-ui/editor/dist/i18n/ko-kr"; import { Editor } from "@toast-ui/react-editor"; import colorSyntax from "@toast-ui/editor-plugin-color-syntax"; -import { Dispatch, LegacyRef, SetStateAction, useEffect, useRef } from "react"; +import { RefObject, useEffect } from "react"; import supabase from "@/lib/supabase"; import imageCompression from "browser-image-compression"; +import { useRecoilState } from "recoil"; +import { postContent as recoilPostContent } from "@/lib/recoil"; /** * @TODO storage 삭제 구현 필요 @@ -16,16 +18,11 @@ import imageCompression from "browser-image-compression"; */ interface PostEditorProps { - postContent: string; - setPostContent: Dispatch>; - editorRef: LegacyRef; + editorRef: RefObject; } -const PostEditor = ({ - postContent, - setPostContent, - editorRef, -}: PostEditorProps) => { +const PostEditor = ({ editorRef }: PostEditorProps) => { + const [postContent, setPostContent] = useRecoilState(recoilPostContent); const toolbarItems = [ ["heading", "bold", "italic", "strike"], ["hr"], @@ -36,18 +33,27 @@ const PostEditor = ({ ["scrollSync"], ]; + // if (editorRef.current) { + // setEditorText(editorRef.current?.getInstance().getMarkdown()); + // } + useEffect(() => { - const editorIns = editorRef.current.getInstance(); - editorIns.removeHook("addImageBlobHook"); - editorIns.addHook("addImageBlobHook", addImage); + if (editorRef.current) { + const editorIns = editorRef.current.getInstance(); + editorIns.removeHook("addImageBlobHook"); + editorIns.addHook("addImageBlobHook", addImage); + } }, []); // ------------- image Function ------------- // 에디터에 이미지 추가 - const addImage = async (blob: File, dropImage) => { - // https://www.youtube.com/watch?v=dLqSmxX3r7I + type HookCallback = (url: string, text?: string) => void; + + const addImage = async (blob: File, dropImage: HookCallback) => { const img = await compressImg(blob); // 이미지 압축 + if (!img) return; const url = await uploadImage(img); // 업로드된 이미지 서버 url + if (!url) return; dropImage(url, `${blob.name}`); // 에디터에 이미지 추가 }; @@ -88,10 +94,10 @@ const PostEditor = ({ // return editorIns.getHTML(); // }; - const handleRegisterButton = () => { + const handleOnEditorChange = () => { // 유효성 검사 const editorText = editorRef.current?.getInstance().getMarkdown(); - if ((editorText === " ") | (editorText === "")) { + if (editorText === " " || editorText === "" || editorText === undefined) { return; } // HTML 대신에 Markdown으로 저장합니다. @@ -114,10 +120,11 @@ const PostEditor = ({ // // 에러 표시 // } // }; + return ( handleOnEditorChange()} /> ); }; diff --git a/Components/Post/PostTitle.tsx b/Components/Post/PostTitle.tsx index 31577617..01593654 100644 --- a/Components/Post/PostTitle.tsx +++ b/Components/Post/PostTitle.tsx @@ -1,42 +1,33 @@ -import React, { Dispatch, SetStateAction, useState } from "react"; +import React from "react"; import styled from "styled-components"; import Image, { StaticImageData } from "next/image"; import image_upload from "@/public/icons/image_upload.svg"; +import { useRecoilState } from "recoil"; +import { + postSubTitle, + postTitle, + postTitleBackgroundColor, +} from "@/lib/recoil"; -interface PostTitleProps { - title: string; - setTitle: Dispatch>; - subTitle: string; - setSubTitle: Dispatch>; - imgFile: string; - setImgFile: Dispatch>; -} /** * @TODO StrictNull 로 오류 발생 * @TODO next Image width와 height 미지정으로 오류 * @TODO input을 커스텀 훅으로 만들기. */ -const PostTitle = ({ - title, - setTitle, - subTitle, - setSubTitle, - imgFile, - setImgFile, -}: PostTitleProps) => { - const onChangeImg = (e: React.ChangeEvent) => { - if (!e.target.files) return; - const file = e.target.files[0]; - const reader = new FileReader(); - reader.readAsDataURL(file); - reader.onloadend = () => { - setImgFile(reader.result as string); - }; +const PostTitle = () => { + const [backgroundColor, setBackgroundColor] = useRecoilState( + postTitleBackgroundColor + ); + const [title, setTitle] = useRecoilState(postTitle); + const [subTitle, setSubTitle] = useRecoilState(postSubTitle); + + const onChangeColor = (e: React.ChangeEvent) => { + setBackgroundColor(e.target.value); }; return ( - + setTitle(e.target.value)} @@ -48,7 +39,7 @@ const PostTitle = ({ onChange={(e) => setSubTitle(e.target.value)} placeholder="소제목을 입력하세요" /> - + - - {imgFile && ( - - )} ); }; @@ -86,6 +66,7 @@ const TitleContainer = styled.div` gap: 1.375rem; border: 1px solid black; position: relative; + background-color: ${(props) => props.color}; `; const TitleInput = styled.input` display: inline-block; @@ -108,16 +89,14 @@ const SubTitleInput = styled.input` font-size: 1.375rem; font-weight: 400; border: none; + background-color: transparent; `; const ImgLabel = styled.label``; const ImgIcon = styled(Image)` cursor: pointer; `; -const ImgInput = styled.input` - display: none; -`; - -const BackgroundImgFile = styled(Image)` - position: absolute; - z-index: -1; +const TitleBackgroundColorPicker = styled.input` + opacity: 0; + width: 0; + height: 0; `; diff --git a/Components/Post/ProjectInfo.tsx b/Components/Post/ProjectInfo.tsx index 55590b5e..ffdc4591 100644 --- a/Components/Post/ProjectInfo.tsx +++ b/Components/Post/ProjectInfo.tsx @@ -1,39 +1,10 @@ import Image from "next/image"; import styled from "styled-components"; -import { Dispatch, SetStateAction, useState } from "react"; +import { useState } from "react"; import arrow_down from "@/public/images/arrow_down.jpg"; import ProjectInfoDropDown from "./ProjectInfoDropDown"; -import { WithPersonType } from "./WithPeople"; -interface ProjectInfoDropDownProps { - startDate: Date; - setStartDate: Dispatch>; - endDate: Date; - setEndDate: Dispatch>; - techStack: string[]; - setTechStack: Dispatch>; - tag: string[]; - setTag: Dispatch>; - isPublic: boolean; - setIsPublic: Dispatch>; - people: WithPersonType[]; - setPeople: Dispatch>; -} - -const ProjectInfo = ({ - startDate, - setStartDate, - endDate, - setEndDate, - techStack, - setTechStack, - tag, - setTag, - isPublic, - setIsPublic, - people, - setPeople, -}: ProjectInfoDropDownProps) => { +const ProjectInfo = () => { const [openDropdown, setOpenDropdown] = useState(false); return ( @@ -44,22 +15,7 @@ const ProjectInfo = ({ - {openDropdown && ( - - )} + {openDropdown && } ); }; diff --git a/Components/Post/ProjectInfoDropDown.tsx b/Components/Post/ProjectInfoDropDown.tsx index e29561ed..e682c614 100644 --- a/Components/Post/ProjectInfoDropDown.tsx +++ b/Components/Post/ProjectInfoDropDown.tsx @@ -1,58 +1,35 @@ import styled from "styled-components"; -import { Dispatch, SetStateAction, useState } from "react"; +import { useState } from "react"; +import { useRecoilState, useRecoilValue } from "recoil"; +import { + postLargeCategory, + postProjectDuration, + postPublic, + postSkills, + postSubCategory, + postTags, +} from "@/lib/recoil"; import "react-datepicker/dist/react-datepicker.css"; import DatePicker from "react-datepicker"; +import getYYYYMM from "@/utils/commons/getYYYYMM"; import FieldDropDown from "./FieldDropDown"; import SkillList from "../Common/Skill/SkillList"; import Toggle from "../Common/Toggle"; -import WithPeople, { WithPersonType } from "./WithPeople"; +import WithPeople from "./WithPeople"; +import Tags from "../Common/Tags"; /** * @see https://www.youtube.com/shorts/4hpjO2onpNs * @TODO 월 선택 안됨 (z-index) */ -interface ProjectInfoDropDownProps { - startDate: Date; - setStartDate: Dispatch>; - endDate: Date; - setEndDate: Dispatch>; - techStack: string[]; - setTechStack: Dispatch>; - tag: string[]; - setTag: Dispatch>; - isPublic: boolean; - setIsPublic: Dispatch>; - people: WithPersonType[]; - setPeople: Dispatch>; -} - -const ProjectInfoDropDown = ({ - startDate, - setStartDate, - endDate, - setEndDate, - techStack, - setTechStack, - tag, - setTag, - isPublic, - setIsPublic, - people, - setPeople, -}: ProjectInfoDropDownProps) => { - const [inputValue, setInputValue] = useState(""); - const [selectedItem, setSelectedItem] = useState(""); - - const handleOnPush = (e: React.KeyboardEvent) => { - if (e.key === "Enter") { - setTechStack((prev) => [...prev, inputValue]); - setInputValue(""); - } - }; - const handleOnChange = (e: React.ChangeEvent) => { - setInputValue(e.target.value); - }; +const ProjectInfoDropDown = () => { + const [postSkill, setPostSkill] = useRecoilState(postSkills); + const [[startDate, endDate], setDate] = useRecoilState(postProjectDuration); + const [tag, setTag] = useRecoilState(postTags); + const [isPublic, setIsPublic] = useRecoilState(postPublic); + const largeCategory = useRecoilValue(postLargeCategory); + const subCategory = useRecoilValue(postSubCategory); const [categoryVisible, setCategoryVisible] = useState(false); @@ -65,19 +42,21 @@ const ProjectInfoDropDown = ({ 카테고리 - - 카테고리를 선택해주세요. - {categoryVisible && ( - - )} - + {largeCategory && subCategory ? ( + ${subCategory}`]} size="md" /> + ) : ( + + 카테고리를 선택해주세요. + {categoryVisible && } + + )} 개발 스택 @@ -85,23 +64,27 @@ const ProjectInfoDropDown = ({ setStartDate(date)} + onChange={(date: Date) => + setDate((prev) => [getYYYYMM(date), prev[1]]) + } selectsStart - startDate={startDate} - endDate={endDate} + startDate={new Date(startDate)} + endDate={new Date(endDate)} /> ~ setEndDate(date)} + onChange={(date: Date) => + setDate((prev) => [prev[0], getYYYYMM(date)]) + } selectsEnd - startDate={startDate} - endDate={endDate} - minDate={startDate} + startDate={new Date(startDate)} + endDate={new Date(endDate)} + minDate={new Date(startDate)} /> @@ -109,7 +92,7 @@ const ProjectInfoDropDown = ({ 함께한 사람들 - + 키워드 태그 @@ -119,7 +102,7 @@ const ProjectInfoDropDown = ({ 게시물 공개 -

    비공개

    +

    {isPublic ? "공개" : "비공개"}

    diff --git a/Components/Post/WithPeople.tsx b/Components/Post/WithPeople.tsx index 326a1b32..fb87b752 100644 --- a/Components/Post/WithPeople.tsx +++ b/Components/Post/WithPeople.tsx @@ -1,19 +1,11 @@ +import { postMembers } from "@/lib/recoil"; import Image from "next/image"; import { ChangeEvent, Dispatch, SetStateAction } from "react"; +import { useRecoilState } from "recoil"; import styled from "styled-components"; -export interface WithPersonType { - name: string; - field: string; - github: string; -} - -interface WithPeopleProps { - people: WithPersonType[]; - setPeople: Dispatch>; -} - -const WithPeople = ({ people, setPeople }: WithPeopleProps) => { +const WithPeople = () => { + const [people, setPeople] = useRecoilState(postMembers); const addPerson = () => { if (people.length === 0) { setPeople([...people, { name: "", field: "", github: "" }]); diff --git a/lib/recoil/index.ts b/lib/recoil/index.ts index 66904206..22ce9750 100644 --- a/lib/recoil/index.ts +++ b/lib/recoil/index.ts @@ -1,3 +1,30 @@ import { largeCategoryState, subCategoryState } from "@/lib/recoil/atoms"; +import { + postTitle, + postSubTitle, + postTitleBackgroundColor, + postLargeCategory, + postSubCategory, + postSkills, + postProjectDuration, + postMembers, + postTags, + postPublic, + postContent, +} from "@/lib/recoil/postAtoms"; -export { largeCategoryState, subCategoryState }; +export { + largeCategoryState, + subCategoryState, + postTitle, + postSubTitle, + postTitleBackgroundColor, + postLargeCategory, + postSubCategory, + postSkills, + postProjectDuration, + postMembers, + postTags, + postPublic, + postContent, +}; diff --git a/lib/recoil/postAtoms.ts b/lib/recoil/postAtoms.ts new file mode 100644 index 00000000..3a184b09 --- /dev/null +++ b/lib/recoil/postAtoms.ts @@ -0,0 +1,77 @@ +import getYYYYMM from "@/utils/commons/getYYYYMM"; +import { atom } from "recoil"; + +const postTitle = atom({ + key: "postTitle", + default: "", +}); + +const postSubTitle = atom({ + key: "postSubTitle", + default: "", +}); + +const postTitleBackgroundColor = atom({ + key: "postTitleBackgroundColor", + default: "#fff", +}); + +const postLargeCategory = atom({ + key: "postLargeCategory", + default: "웹", +}); + +const postSubCategory = atom({ + key: "postSubCategory", + default: "", +}); + +const postSkills = atom({ + key: "postSkills", + default: [], +}); + +const postProjectDuration = atom<[string, string]>({ + key: "postProjectDuration", + default: [getYYYYMM(), getYYYYMM()], +}); + +interface MembersType { + name: string; + field: string; + github: string; +} + +const postMembers = atom({ + key: "postMembers", + default: [], +}); + +const postTags = atom({ + key: "postTags", + default: [], +}); + +const postPublic = atom({ + key: "postPublic", + default: false, +}); + +const postContent = atom({ + key: "postContent", + default: "", +}); + +export { + postTitle, + postSubTitle, + postTitleBackgroundColor, + postLargeCategory, + postSubCategory, + postSkills, + postProjectDuration, + postMembers, + postTags, + postPublic, + postContent, +}; diff --git a/pages/create-post.tsx b/pages/create-post.tsx index 01481697..d0da3516 100644 --- a/pages/create-post.tsx +++ b/pages/create-post.tsx @@ -1,12 +1,20 @@ -import GNB from "@/Components/Layouts/GNB"; import Post from "@/Components/Post/Post"; +import { Editor } from "@toast-ui/react-editor"; import { NextPage, GetServerSideProps } from "next"; +import dynamic from "next/dynamic"; +import { useRef } from "react"; const CreatePostPage: NextPage = () => { + const editorRef = useRef(null); + + const PostEditor = dynamic(() => import("@/Components/Post/PostEditor"), { + ssr: false, + }); + return ( <> - + ); }; diff --git a/types.d.ts b/types.d.ts index 343da65d..f0b59d64 100644 --- a/types.d.ts +++ b/types.d.ts @@ -87,23 +87,19 @@ interface NotificationType { } declare interface PostType { - id: string; - user_id: string; title: string; sub_title: string; - content: string; - thumbnail: string; - progress_date: [string, string]; - github_url: string; - url: string; - is_public: boolean; - members: WithPersonType[]; + title_background_color: string; + large_category: string; + sub_category: string; skills: string[]; + progress_date: string[]; + members: MembersType[]; tag: string[]; - created_at: Date; - large_category: FiledType; - sub_category: SubCategory; - // + is_public: boolean; + content: string; + id: string; + user_id: string; } interface FollowType { diff --git a/utils/commons/getYYYYMM.ts b/utils/commons/getYYYYMM.ts new file mode 100644 index 00000000..2c3aec72 --- /dev/null +++ b/utils/commons/getYYYYMM.ts @@ -0,0 +1,7 @@ +const getYYYYMM = (date = new Date()) => { + const year = date.getFullYear(); + const month = date.getMonth() + 1; + return `${year}-${month < 10 ? `0${month}` : month}`; +}; + +export default getYYYYMM; diff --git a/yarn.lock b/yarn.lock index f25ea9e2..0918d6ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -409,6 +409,13 @@ dependencies: tslib "^2.4.0" +"@toast-ui/editor-plugin-color-syntax@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@toast-ui/editor-plugin-color-syntax/-/editor-plugin-color-syntax-3.1.0.tgz#afbaabe7fe315bf6b6c3d9a62564878d0a365549" + integrity sha512-UVKfMBPV+3snSaJn9RUKGbxJbgi92D2t68ow8wAjGezvMp1ht4UVETrvomdTGr+RYhXSeH3JvSwN9nmQqw0qzA== + dependencies: + tui-color-picker "^2.2.6" + "@toast-ui/editor@^3.2.1": version "3.2.1" resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-3.2.1.tgz#dcd0b7471299842b2962aab5d757723a61959f2a" @@ -796,6 +803,13 @@ broadcast-channel@^3.4.1: rimraf "3.0.2" unload "2.2.0" +browser-image-compression@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/browser-image-compression/-/browser-image-compression-2.0.0.tgz#f421381a76d474d4da7dcd82810daf595b09bef6" + integrity sha512-kBlkZo13yOOfcmrPW0M0K/UdZPogIQj2gRvXIM3FktAnfW6VRq9aY2RI+F6O0x6DMj1Xm+WLGgWcFK8Fu/ddnw== + dependencies: + uzip "0.20201231.0" + bufferutil@^4.0.1: version "4.0.7" resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" @@ -1431,7 +1445,7 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.0.1: +eslint@8.33.0: version "8.33.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.33.0.tgz#02f110f32998cb598c6461f24f4d306e41ca33d7" integrity sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA== @@ -2851,6 +2865,11 @@ source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +ssr-window@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/ssr-window/-/ssr-window-4.0.2.tgz#dc6b3ee37be86ac0e3ddc60030f7b3bc9b8553be" + integrity sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ== + stop-iteration-iterator@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" @@ -2958,6 +2977,13 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +swiper@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/swiper/-/swiper-9.0.5.tgz#cd6b6520d2431e3809f51fb8682f5a37e8295e4a" + integrity sha512-UiLQ5fvn8L3ZZpaPa+9oiwKwhVGQt5TVc0UuXxFKHyTQe8g2E3vbPMiMfIGb6NhNGj5ntsSDyyNgg4qVmWlJkQ== + dependencies: + ssr-window "^4.0.2" + synckit@^0.8.4: version "0.8.5" resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3" @@ -3040,6 +3066,11 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tui-color-picker@^2.2.6: + version "2.2.8" + resolved "https://registry.yarnpkg.com/tui-color-picker/-/tui-color-picker-2.2.8.tgz#8e140ab04066dbdb2353c4a1f434ad7d8d7b0d73" + integrity sha512-q5sE9NQ5NR9lYpilYjcI7Sdv0KCogo+W8fZY+AYTj/HYg+9fscYy3UuJ6UQiV1bF+ARCLwFRWC8UcOt9kuUctQ== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -3078,7 +3109,7 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@*: +typescript@4.9.5: version "4.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== @@ -3115,6 +3146,11 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.3.0" +uzip@0.20201231.0: + version "0.20201231.0" + resolved "https://registry.yarnpkg.com/uzip/-/uzip-0.20201231.0.tgz#9e64b065b9a8ebf26eb7583fe8e77e1d9a15ed14" + integrity sha512-OZeJfZP+R0z9D6TmBgLq2LHzSSptGMGDGigGiEe0pr8UBe/7fdflgHlHBNDASTXB5jnFuxHpNaJywSg8YFeGng== + w3c-keyname@^2.2.0: version "2.2.6" resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.6.tgz#8412046116bc16c5d73d4e612053ea10a189c85f" From 118f27f4ea139b8580b8955bf3023a4ace3e7c03 Mon Sep 17 00:00:00 2001 From: arch-spatula Date: Wed, 15 Feb 2023 22:44:31 +0900 Subject: [PATCH 60/61] =?UTF-8?q?docs(PostEditor,=20types):=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EB=B0=8F=20?= =?UTF-8?q?=ED=82=A4=EC=9B=8C=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PostEditor의 불필요한 주석을 삭제합니다. - types.d.ts의 declare를 삭제합니다. #5 --- Components/Post/PostEditor.tsx | 36 +--------------------------------- types.d.ts | 2 +- 2 files changed, 2 insertions(+), 36 deletions(-) diff --git a/Components/Post/PostEditor.tsx b/Components/Post/PostEditor.tsx index 7d665ec2..08d728e9 100644 --- a/Components/Post/PostEditor.tsx +++ b/Components/Post/PostEditor.tsx @@ -33,10 +33,6 @@ const PostEditor = ({ editorRef }: PostEditorProps) => { ["scrollSync"], ]; - // if (editorRef.current) { - // setEditorText(editorRef.current?.getInstance().getMarkdown()); - // } - useEffect(() => { if (editorRef.current) { const editorIns = editorRef.current.getInstance(); @@ -87,13 +83,6 @@ const PostEditor = ({ editorRef }: PostEditorProps) => { return result; }; - // detail에 활용 가능 - // const getContent = () => { - // //글 내용 HTML 문자열로 불러오기 - // const editorIns = editorRef.current.getInstance(); - // return editorIns.getHTML(); - // }; - const handleOnEditorChange = () => { // 유효성 검사 const editorText = editorRef.current?.getInstance().getMarkdown(); @@ -104,23 +93,6 @@ const PostEditor = ({ editorRef }: PostEditorProps) => { setPostContent(editorText); }; - // 진행 해야 함 - // const getMarkDown = () => { - // //글 내용 마크다운 문자열로 불러오기 - // const editorIns = editorRef.current.getInstance(); - // return editorIns.getMarkdown(); - // }; - - // const validation_check = () => { - // const title = titleRef.current.value.trim(); - // const content = getMarkDown(); - // if (title !== "" || content !== "") { - // // DB에 저장 - // } else { - // // 에러 표시 - // } - // }; - return ( { useCommandShortcut toolbarItems={toolbarItems} language="ko-KR" - plugins={[ - colorSyntax, - // 기본 색상 preset 적용 - // { - // preset: ["#1F2E3D", "#4c5864", "#ED7675"], - // }, - ]} + plugins={[colorSyntax]} hooks={{ // @ts-ignore addImageBlobHook: addImage, diff --git a/types.d.ts b/types.d.ts index f0b59d64..40a7a9a9 100644 --- a/types.d.ts +++ b/types.d.ts @@ -86,7 +86,7 @@ interface NotificationType { target_id: string; } -declare interface PostType { +interface PostType { title: string; sub_title: string; title_background_color: string; From 2cb53a532f5520401f0937b586e8dcf0b46566fb Mon Sep 17 00:00:00 2001 From: Jeremy-kr Date: Thu, 16 Feb 2023 09:39:36 +0900 Subject: [PATCH 61/61] =?UTF-8?q?fix:=20PR=20=EC=A4=91=20=ED=94=BC?= =?UTF-8?q?=EB=93=9C=EB=B0=B1=EC=9D=84=20=EB=B0=98=EC=98=81=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Components/Post/Post.tsx | 10 ++-------- Components/Post/PostTitle.tsx | 8 +++----- Components/Post/ProjectInfoDropDown.tsx | 5 ----- public/icons/color_fill.svg | 3 +++ 4 files changed, 8 insertions(+), 18 deletions(-) create mode 100644 public/icons/color_fill.svg diff --git a/Components/Post/Post.tsx b/Components/Post/Post.tsx index 4664fc41..88591a4b 100644 --- a/Components/Post/Post.tsx +++ b/Components/Post/Post.tsx @@ -18,18 +18,12 @@ import { postTitleBackgroundColor, } from "@/lib/recoil"; import supabase from "@/lib/supabase"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { useRouter } from "next/router"; /** - * @TODO 코드블럭 - * @TODO 게시 전 입력창 추가(인원, 기간 등 - 피그마 참고) - * @TODO file(img) input 에서 color picker로 변경 - * @TODO date picker z-index 해결 - * @TODO Date recoil을 활용한 custom hook으로 리팩토링하기 - * @TODO 개발스택 UI my-page 참고 + * @TODO custom hook으로 리팩토링하기 * @TODO 카테고리 중복 선택 , 보여주는 UI - * @TODO 서버통신 연결 */ const Post: NextPage = () => { const title = useRecoilValue(postTitle); diff --git a/Components/Post/PostTitle.tsx b/Components/Post/PostTitle.tsx index 01593654..d704cbe9 100644 --- a/Components/Post/PostTitle.tsx +++ b/Components/Post/PostTitle.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled from "styled-components"; import Image, { StaticImageData } from "next/image"; -import image_upload from "@/public/icons/image_upload.svg"; +import color_fill from "@/public/icons/color_fill.svg"; import { useRecoilState } from "recoil"; import { postSubTitle, @@ -10,8 +10,6 @@ import { } from "@/lib/recoil"; /** - * @TODO StrictNull 로 오류 발생 - * @TODO next Image width와 height 미지정으로 오류 * @TODO input을 커스텀 훅으로 만들기. */ @@ -41,8 +39,8 @@ const PostTitle = () => { /> diff --git a/Components/Post/ProjectInfoDropDown.tsx b/Components/Post/ProjectInfoDropDown.tsx index e682c614..edfed800 100644 --- a/Components/Post/ProjectInfoDropDown.tsx +++ b/Components/Post/ProjectInfoDropDown.tsx @@ -18,11 +18,6 @@ import Toggle from "../Common/Toggle"; import WithPeople from "./WithPeople"; import Tags from "../Common/Tags"; -/** - * @see https://www.youtube.com/shorts/4hpjO2onpNs - * @TODO 월 선택 안됨 (z-index) - */ - const ProjectInfoDropDown = () => { const [postSkill, setPostSkill] = useRecoilState(postSkills); const [[startDate, endDate], setDate] = useRecoilState(postProjectDuration); diff --git a/public/icons/color_fill.svg b/public/icons/color_fill.svg new file mode 100644 index 00000000..122c1bc1 --- /dev/null +++ b/public/icons/color_fill.svg @@ -0,0 +1,3 @@ + + +