From 177ccbe90a6c1ff5e6691d2c07364448b89724b1 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 14 Jun 2021 09:50:40 +0900 Subject: [PATCH 01/71] =?UTF-8?q?chore:=20=EB=A6=AC=EC=BD=94=EC=9D=BC=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/pages/MainPage.jsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/frontend/src/components/pages/MainPage.jsx b/frontend/src/components/pages/MainPage.jsx index 6900eea12..56bbf7923 100644 --- a/frontend/src/components/pages/MainPage.jsx +++ b/frontend/src/components/pages/MainPage.jsx @@ -9,8 +9,6 @@ import Milestones from "components/Milestones/Milestones"; import Header from "components/common/Header"; import Navigator from "components/common/Navigator"; import Issues from "components/Issues/Issues"; -import { Test } from "components/pages/Test"; -import { AnotherTest } from "./AnotherTest"; const MainPage = () => { const { pathname } = window.location; @@ -18,17 +16,14 @@ const MainPage = () => { return localStorage.getItem("accessToken") ? (
- {(pathname === "/main/labels" || pathname === "/main/milestones") && ( )} {pathname === "/main" && } - - From 3edf118fb53a4347733b69fa338c8e0ca9c19f43 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 14 Jun 2021 14:33:17 +0900 Subject: [PATCH 02/71] =?UTF-8?q?WIP:=20=EC=9D=B4=EC=8A=88=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Issues/IssueList/IssueCard.jsx | 19 ++++++++++---- .../components/Issues/IssueList/IssueList.jsx | 25 ++++++++++++++++--- .../Issues/IssueList/IssuesHeader.jsx | 12 ++++++--- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index 22c239d86..d0b7225ce 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -6,12 +6,18 @@ import { ReactComponent as Alert } from "images/alert-circle.svg"; import { ReactComponent as Milestone } from "images/milestone.svg"; import getTimeStamp from "util/getTimeStamp"; -const IssueCard = ({ issue }) => { +const IssueCard = ({ + issue, + isAnyIssueSelected, + setIsAnyIssueSelected, + isAllIssueSelected, + setIsAllIssueSelected, +}) => { const { title, id, labelId, milestoneId, author, createdAt } = issue; return ( - +
-
@@ -19,17 +25,20 @@ const IssueCard = ({ issue }) => { {title} - {labelId} {/* labelId 로 라벨 정보 fetch 해와서 title, 박스 렌더링 */} + {labelId}{" "} + {/* labelId 로 라벨 정보 fetch 해와서 title, 박스 렌더링 */} #{id} - 이 이슈가 {getTimeStamp(createdAt)}, {author}님에 의해 작성되었습니다 + 이 이슈가 {getTimeStamp(createdAt)}, {author}님에 의해 + 작성되었습니다 - {milestoneId} {/* milestoneId 로 마일스톤 정보 fetch 해와서 title만 뿌리기 */} + {milestoneId}{" "} + {/* milestoneId 로 마일스톤 정보 fetch 해와서 title만 뿌리기 */} diff --git a/frontend/src/components/Issues/IssueList/IssueList.jsx b/frontend/src/components/Issues/IssueList/IssueList.jsx index 90c5f42f8..d5701e4ef 100644 --- a/frontend/src/components/Issues/IssueList/IssueList.jsx +++ b/frontend/src/components/Issues/IssueList/IssueList.jsx @@ -5,12 +5,29 @@ import IssueCard from "./IssueCard"; import { issues } from "data"; const IssueList = () => { - const issueList = issues.map((issue) => ); - // const [isIssueSelected, setIsIssueSelected] = useState(false); // 상태 위치 협의 후 수정 - // const [isAllIssueSelected, setIsAllIssueSelected] = useState(false); + const [isAnyIssueSelected, setIsAnyIssueSelected] = useState(false); // 상태 위치 협의 후 수정 + const [isAllIssueSelected, setIsAllIssueSelected] = useState(false); + const [selectedIssues, setSelectedIssues] = useState([]); + + const issueList = issues.map(issue => ( + + )); + return ( - + {issueList} ); diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index 0bcb768b1..2dc25adb1 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -6,10 +6,14 @@ import { ReactComponent as DownArrow } from "images/chevron_down.svg"; import theme from "styles/theme"; import { useEffect } from "react"; -const IssuesHeader = ({}) => { +const IssuesHeader = ({ + isAnyIssueSelected, + setIsAnyIssueSelected, + isAllIssueSelected, + setIsAllIssueSelected, +}) => { const [isIssueOpenFilter, setIsIssueOpenFilter] = useState(true); // means issueOpen clicked - const [isIssueSelected, setIsIssueSelected] = useState(false); // 상태 위치 협의 후 수정 - const [isAllIssueSelected, setIsAllIssueSelected] = useState(false); + const checkAllIssue = () => { setIsAllIssueSelected(!isAllIssueSelected); }; @@ -32,7 +36,7 @@ const IssuesHeader = ({}) => { - {isIssueSelected ? ( + {isAnyIssueSelected ? ( 상태 수정 From 69b6d82b535c37d5c2384cdc16c30599ce540015 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 14 Jun 2021 15:02:21 +0900 Subject: [PATCH 03/71] =?UTF-8?q?feat:=20=EC=B2=B4=ED=81=AC=EB=B0=95?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=90=EC=B0=A8=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Issues/IssueList/IssueCard.jsx | 14 +++++++++++++- .../src/components/Issues/Menu/MenuFilterBar.jsx | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index d0b7225ce..e533e9a7b 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -1,3 +1,4 @@ +import { useState, useEffect } from "react"; import styled from "styled-components"; import theme from "styles/theme"; import { Link } from "react-router-dom"; @@ -13,11 +14,22 @@ const IssueCard = ({ isAllIssueSelected, setIsAllIssueSelected, }) => { + const [isChecked, setIsChecked] = useState(false); const { title, id, labelId, milestoneId, author, createdAt } = issue; + + const handleCheck = () => { + setIsChecked(!isChecked); + }; + + useEffect(() => { + if (isAllIssueSelected) setIsChecked(true); + else if (!isAllIssueSelected) setIsChecked(false); + }, [isAllIssueSelected]); + return ( - +
-
diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index cc99f5c21..a57a294d1 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -37,7 +37,7 @@ const MenuFilterBar = () => { - {} + {/* {} */} ); }; From d993d06274711e2921026e1b0ed797448699a3da Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 14 Jun 2021 15:07:55 +0900 Subject: [PATCH 04/71] =?UTF-8?q?fix:=20=ED=83=80=EC=9E=84=EC=8A=A4?= =?UTF-8?q?=ED=83=AC=ED=94=84=20=EC=9C=A0=ED=8B=B8=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/data.js | 4 ++-- frontend/src/util/getTimeStamp.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/data.js b/frontend/src/data.js index 61f8e22e8..de712035f 100644 --- a/frontend/src/data.js +++ b/frontend/src/data.js @@ -5,7 +5,7 @@ export const issues = [ labelId: 2, milestoneId: 4, author: "goody", - createdAt: "2021-06-10", + createdAt: "2021-06-10T23:50:14", isOpen: true, }, { @@ -14,7 +14,7 @@ export const issues = [ labelId: 2, milestoneId: 4, author: "daisy", - createdAt: "2021-06-11", + createdAt: "2021-06-14T15:00:00", isOpen: false, }, ]; diff --git a/frontend/src/util/getTimeStamp.js b/frontend/src/util/getTimeStamp.js index 7da892d8e..68d863fb4 100644 --- a/frontend/src/util/getTimeStamp.js +++ b/frontend/src/util/getTimeStamp.js @@ -1,4 +1,4 @@ -const getTimeStamp = (dateInfo) => { +const getTimeStamp = dateInfo => { const now = new Date(); const logTime = new Date(dateInfo); const diff = Math.floor((now.getTime() - logTime.getTime()) / 1000 / 60); @@ -8,7 +8,7 @@ const getTimeStamp = (dateInfo) => { const diffHour = Math.floor(diff / 60); if (diffHour < 24) return `${diffHour}시간 전`; - const diffDay = Math.floor(diffHour / 60 / 24); + const diffDay = Math.floor(diffHour / 24); if (diffDay < 365) return `${diffDay}일 전`; return `${Math.floor(diffDay / 365)}년 전`; From ab611f63b28347c53f637f442a7abc8a5dd05b7e Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 14 Jun 2021 20:58:53 +0900 Subject: [PATCH 05/71] =?UTF-8?q?feat:=20=EC=9D=B4=EC=8A=88=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9D=B4=EC=8A=88=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=EB=B0=95=EC=8A=A4=EB=A1=9C=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/MyRecoil/atom.js | 5 ++ frontend/src/MyRecoil/useRecoilState.js | 1 - .../components/Issues/IssueList/IssueCard.jsx | 30 ++++++++--- .../components/Issues/IssueList/IssueList.jsx | 19 +++++-- .../Issues/IssueList/IssuesHeader.jsx | 52 ++++++++++++++----- 5 files changed, 84 insertions(+), 23 deletions(-) diff --git a/frontend/src/MyRecoil/atom.js b/frontend/src/MyRecoil/atom.js index 6c751256c..e85927011 100644 --- a/frontend/src/MyRecoil/atom.js +++ b/frontend/src/MyRecoil/atom.js @@ -26,3 +26,8 @@ export const authorAtomState = atom({ key: "authorAtomState", initialState: [], }); + +export const selectedIssueCntAtomState = atom({ + key: "selectedIssueCntAtomState", + initialState: 0, +}); diff --git a/frontend/src/MyRecoil/useRecoilState.js b/frontend/src/MyRecoil/useRecoilState.js index ed97086f4..c88d34c4b 100644 --- a/frontend/src/MyRecoil/useRecoilState.js +++ b/frontend/src/MyRecoil/useRecoilState.js @@ -8,7 +8,6 @@ export const useRecoilState = atom => { store.setInitState(atom); const forceUpdate = useCallback(() => { - console.log("forced Update"); setReRender({}); }, []); diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index e533e9a7b..1686c29d3 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -6,26 +6,43 @@ import { ReactComponent as UserImageSmall } from "images/UserImageSmall.svg"; import { ReactComponent as Alert } from "images/alert-circle.svg"; import { ReactComponent as Milestone } from "images/milestone.svg"; import getTimeStamp from "util/getTimeStamp"; +import { useRecoilState } from "MyRecoil/useRecoilState"; +import { selectedIssueCntAtomState } from "MyRecoil/atom"; const IssueCard = ({ issue, - isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSelected, setIsAllIssueSelected, + initCheck, + setInitCheck, }) => { const [isChecked, setIsChecked] = useState(false); + const [selectedIssues, setSelectedIssues] = useRecoilState( + selectedIssueCntAtomState + ); + // const [initCheck, setInitCheck] = useState(true); const { title, id, labelId, milestoneId, author, createdAt } = issue; - const handleCheck = () => { setIsChecked(!isChecked); }; useEffect(() => { - if (isAllIssueSelected) setIsChecked(true); - else if (!isAllIssueSelected) setIsChecked(false); + if (isAllIssueSelected) { + setIsChecked(true); + } else if (!isAllIssueSelected) setIsChecked(false); }, [isAllIssueSelected]); + useEffect(() => { + if (isChecked) { + setIsAnyIssueSelected(true); + setSelectedIssues(() => selectedIssues + 1); + setInitCheck(false); + } else if (!initCheck && !isChecked) { + setSelectedIssues(() => selectedIssues - 1); + } + }, [isChecked]); + return ( @@ -37,7 +54,7 @@ const IssueCard = ({ {title} - {labelId}{" "} + {/* labelId 로 라벨 정보 fetch 해와서 title, 박스 렌더링 */} @@ -47,9 +64,8 @@ const IssueCard = ({ 작성되었습니다 - + - {milestoneId}{" "} {/* milestoneId 로 마일스톤 정보 fetch 해와서 title만 뿌리기 */} diff --git a/frontend/src/components/Issues/IssueList/IssueList.jsx b/frontend/src/components/Issues/IssueList/IssueList.jsx index d5701e4ef..15f91e7bc 100644 --- a/frontend/src/components/Issues/IssueList/IssueList.jsx +++ b/frontend/src/components/Issues/IssueList/IssueList.jsx @@ -1,32 +1,45 @@ -import { useContext, useState } from "react"; +import { useContext, useState, useEffect } from "react"; import styled from "styled-components"; import IssuesHeader from "./IssuesHeader"; import IssueCard from "./IssueCard"; import { issues } from "data"; +import { selectedIssueCntAtomState } from "MyRecoil/atom"; +import { useRecoilState } from "MyRecoil/useRecoilState"; const IssueList = () => { const [isAnyIssueSelected, setIsAnyIssueSelected] = useState(false); // 상태 위치 협의 후 수정 const [isAllIssueSelected, setIsAllIssueSelected] = useState(false); - const [selectedIssues, setSelectedIssues] = useState([]); + const [initCheck, setInitCheck] = useState(true); + const [selectedIssues, setSelectedIssues] = useRecoilState( + selectedIssueCntAtomState + ); + useEffect(() => { + if (!initCheck && !isAllIssueSelected && !isAnyIssueSelected) + setSelectedIssues(() => 0); + }, [isAnyIssueSelected]); const issueList = issues.map(issue => ( )); return ( {issueList} diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index 2dc25adb1..270f5c4e6 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -1,40 +1,68 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import styled from "styled-components"; import { ReactComponent as Archive } from "images/archive.svg"; import { ReactComponent as Alert } from "images/alert-circle.svg"; import { ReactComponent as DownArrow } from "images/chevron_down.svg"; import theme from "styles/theme"; -import { useEffect } from "react"; +import { selectedIssueCntAtomState } from "MyRecoil/atom"; +import { useRecoilState } from "MyRecoil/useRecoilState"; const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSelected, setIsAllIssueSelected, + issuesCnt, + initCheck, + setInitCheck, }) => { - const [isIssueOpenFilter, setIsIssueOpenFilter] = useState(true); // means issueOpen clicked + const [selectedIssues, setSelectedIssues] = useRecoilState( + selectedIssueCntAtomState + ); const checkAllIssue = () => { setIsAllIssueSelected(!isAllIssueSelected); }; useEffect(() => { - isAllIssueSelected && console.log("issue checkbox all selected"); + if (isAllIssueSelected) { + setIsAnyIssueSelected(true); + setInitCheck(false); + setSelectedIssues(() => issuesCnt); + } + if (!initCheck && !isAllIssueSelected) { + setIsAnyIssueSelected(false); + setSelectedIssues(() => 0); + } }, [isAllIssueSelected]); + useEffect(() => { + if (selectedIssues === 0) setIsAnyIssueSelected(false); + if (isAllIssueSelected && selectedIssues === 1) + setIsAnyIssueSelected(false); + }, [selectedIssues]); + return ( - - - 열린 이슈(n) - - - 닫힌 이슈(n) - - + {isAnyIssueSelected ? ( + isAllIssueSelected ? ( +
{selectedIssues - 1}개 이슈 선택
+ ) : ( +
{selectedIssues}개 이슈 선택
+ ) + ) : ( + + + 열린 이슈(n) + + + 닫힌 이슈(n) + + + )} {isAnyIssueSelected ? ( From fd8b1c58a0a7ba72f660118474dde19926ec6960 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 14 Jun 2021 21:18:19 +0900 Subject: [PATCH 06/71] =?UTF-8?q?feat:=20=EC=9D=B4=EC=8A=88=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=97=86=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Issues/IssueList/IssueList.jsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Issues/IssueList/IssueList.jsx b/frontend/src/components/Issues/IssueList/IssueList.jsx index 15f91e7bc..7fe889926 100644 --- a/frontend/src/components/Issues/IssueList/IssueList.jsx +++ b/frontend/src/components/Issues/IssueList/IssueList.jsx @@ -41,7 +41,11 @@ const IssueList = () => { initCheck={initCheck} setInitCheck={setInitCheck} /> - {issueList} + {issueList.length ? ( + issueList + ) : ( + 검색과 일치하는 결과가 없습니다 + )} ); }; @@ -53,3 +57,12 @@ const StyledIssueList = styled.div` flex-direction: column; width: 100%; `; + +const ErrorCard = styled.div` + display: flex; + justify-content: center; + align-items: center; + background-color: ${({ theme }) => theme.grayScale.off_white}; + border: 1px solid ${({ theme }) => theme.grayScale.line}; + height: 100px; +`; From 3d9d6dd5ef740aa719cc8e448b31b8ce33db45a0 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 14 Jun 2021 21:45:17 +0900 Subject: [PATCH 07/71] =?UTF-8?q?feat:=20=EC=84=A0=ED=83=9D=EB=90=9C=20?= =?UTF-8?q?=EC=9D=B4=EC=8A=88=20id=20=EB=A5=BC=20Set=EC=9E=90=EB=A3=8C?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=EB=A1=9C=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Issues/IssueList/IssueCard.jsx | 4 ++++ frontend/src/components/Issues/IssueList/IssueList.jsx | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index 1686c29d3..8c5a9e6e6 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -16,6 +16,8 @@ const IssueCard = ({ setIsAllIssueSelected, initCheck, setInitCheck, + selectedCards, + setSelectedCards, }) => { const [isChecked, setIsChecked] = useState(false); const [selectedIssues, setSelectedIssues] = useRecoilState( @@ -38,8 +40,10 @@ const IssueCard = ({ setIsAnyIssueSelected(true); setSelectedIssues(() => selectedIssues + 1); setInitCheck(false); + setSelectedCards(() => selectedCards.add(id)); } else if (!initCheck && !isChecked) { setSelectedIssues(() => selectedIssues - 1); + selectedCards.delete(id); } }, [isChecked]); diff --git a/frontend/src/components/Issues/IssueList/IssueList.jsx b/frontend/src/components/Issues/IssueList/IssueList.jsx index 7fe889926..139af58ee 100644 --- a/frontend/src/components/Issues/IssueList/IssueList.jsx +++ b/frontend/src/components/Issues/IssueList/IssueList.jsx @@ -10,9 +10,9 @@ const IssueList = () => { const [isAnyIssueSelected, setIsAnyIssueSelected] = useState(false); // 상태 위치 협의 후 수정 const [isAllIssueSelected, setIsAllIssueSelected] = useState(false); const [initCheck, setInitCheck] = useState(true); - const [selectedIssues, setSelectedIssues] = useRecoilState( - selectedIssueCntAtomState - ); + const [_, setSelectedIssues] = useRecoilState(selectedIssueCntAtomState); + const [selectedCards, setSelectedCards] = useState(new Set()); + useEffect(() => { if (!initCheck && !isAllIssueSelected && !isAnyIssueSelected) setSelectedIssues(() => 0); @@ -27,6 +27,8 @@ const IssueList = () => { setIsAllIssueSelected={setIsAllIssueSelected} initCheck={initCheck} setInitCheck={setInitCheck} + selectedCards={selectedCards} + setSelectedCards={setSelectedCards} /> )); From 8218368538eb6821a227ee8f01dffd397e71324d Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 14 Jun 2021 22:03:47 +0900 Subject: [PATCH 08/71] =?UTF-8?q?chore:=20=EC=9D=B4=EC=8A=88=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EA=B0=84=EA=B2=A9=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Issues/IssueList/IssueCard.jsx | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index 8c5a9e6e6..b0a80ed37 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -58,19 +58,24 @@ const IssueCard = ({ {title} - - {/* labelId 로 라벨 정보 fetch 해와서 title, 박스 렌더링 */} + + 라벨 위치 + {/* labelId 로 라벨 정보 fetch 해와서 title, 라벨 렌더링 */} + #{id} - + 이 이슈가 {getTimeStamp(createdAt)}, {author}님에 의해 작성되었습니다 - - + + - - {/* milestoneId 로 마일스톤 정보 fetch 해와서 title만 뿌리기 */} + + + 마일스톤 이름 + {/* milestoneId 로 마일스톤 정보 fetch 해와서 title만 뿌리기 */} + @@ -84,7 +89,7 @@ export default IssueCard; const StyleCard = styled.div` display: grid; - grid-template-columns: 0.5fr 9fr 1fr; + grid-template-columns: 0.5fr 9fr 0.6fr; background-color: ${theme.grayScale.off_white}; border: 1px solid ${theme.grayScale.line}; height: 100px; @@ -109,8 +114,8 @@ const Contents = styled.div` flex-direction: column; `; -const TextTagDivider = styled.div` - display: flex; - /* justify-content: space-between; */ - /* width: 30%; */ +const TextTagDivider = styled.div``; + +const Padder = styled.span` + padding: 0 5px; `; From 17d7a3f7561938bb8c0c0a5e1d7eac62504ff952 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Mon, 14 Jun 2021 23:28:18 +0900 Subject: [PATCH 09/71] =?UTF-8?q?refactor:=20TabButton=20=EC=9E=AC?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=84=B1=20=EB=86=92=EC=9D=B4=EB=8A=94=20?= =?UTF-8?q?=EB=B0=A9=ED=96=A5=EC=9C=BC=EB=A1=9C=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81(#29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/common/ButtonGroup.jsx | 24 +++++++++++--- .../src/components/common/DropDownButton.jsx | 13 ++++++-- frontend/src/styles/StyledButtons.jsx | 31 ++++++++++++------- frontend/src/styles/theme.js | 17 +++++++++- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/common/ButtonGroup.jsx b/frontend/src/components/common/ButtonGroup.jsx index 65e8059ff..157ecc583 100644 --- a/frontend/src/components/common/ButtonGroup.jsx +++ b/frontend/src/components/common/ButtonGroup.jsx @@ -1,24 +1,38 @@ -import { ButtonGroupLeftBtn, ButtonGroupRightBtn } from "styles/StyledButtons"; +import { + ButtonGroupLeftBtn, + ButtonGroupRightBtn, + TabButton, +} from "styles/StyledButtons"; import styled from "styled-components"; import { ReactComponent as LabelIcon } from "images/tag.svg"; import { ReactComponent as MileStoneIcon } from "images/milestone.svg"; import theme from "styles/theme"; + const ButtonGroup = ({ milestoneCount, milestoneClickEvent, labelCount, labelClickEvent, + buttonText, }) => { return ( <> - + theme.buttonWidths.base} + _radius={"left"} + > 마일스톤 ({milestoneCount}) - - + + theme.buttonWidths.base} + _radius={"right"} + > 레이블 ({labelCount}) - + ); }; diff --git a/frontend/src/components/common/DropDownButton.jsx b/frontend/src/components/common/DropDownButton.jsx index 38b79721d..841fa4305 100644 --- a/frontend/src/components/common/DropDownButton.jsx +++ b/frontend/src/components/common/DropDownButton.jsx @@ -2,11 +2,17 @@ import styled from "styled-components"; import { TabButton } from "styles/StyledButtons"; import { ReactComponent as ArrowIcon } from "images/arrow_down.svg"; import theme from "styles/theme"; -const DropDownButton = ({ text, clickEvent }) => { +const DropDownButton = ({ text, clickEvent, width, border, radius }) => { return ( <> - + {text} + {/* theme.grayScale.label} /> 적용 안 됨*/} @@ -14,6 +20,7 @@ const DropDownButton = ({ text, clickEvent }) => { }; const ButtonText = styled.div` - padding-right: 60px; + /* outline: red 1px solid; */ + padding-right: 30%; `; export default DropDownButton; diff --git a/frontend/src/styles/StyledButtons.jsx b/frontend/src/styles/StyledButtons.jsx index edc47a6b0..dbacc709d 100644 --- a/frontend/src/styles/StyledButtons.jsx +++ b/frontend/src/styles/StyledButtons.jsx @@ -2,29 +2,36 @@ import styled from "styled-components"; import Button from "@material-ui/core/Button"; export const TabButton = styled(Button)` - width: 160px; - height: 40px; - font-size: ${({theme}) => theme.fontSizes.xs}; + width: ${props => props._width}; + height: ${({ theme }) => theme.buttonHeights.base}; + font-size: ${({ theme }) => theme.fontSizes.xs}; font-weight: bold; color: ${({ theme }) => theme.grayScale.label}; - border: 1px solid ${({ theme }) => theme.grayScale.line}; - border-radius: 11px 0 0 11px; - background-color: ${({theme}) => theme.grayScale.background}; + border: 1px solid + ${props => (props._border === "none" ? "none" : props.theme.grayScale.line)}; + border-radius: ${props => + props._radius === "right" + ? props.theme.border_radius_mix.right + : props._radius === "left" + ? props.theme.border_radius_mix.left + : props.theme.border_radius_mix.all}; + background-color: ${({ theme }) => + theme.grayScale.background}; //str넣었는데 str넣으라고 오류뜸 `; export const ButtonGroupRightBtn = styled(TabButton)` - border-radius: ${({theme}) => theme.border_radius_mix.right}; - + border-radius: ${({ theme }) => theme.border_radius_mix.right}; + width: ${({ theme }) => theme.buttonWidths.base}; `; export const ButtonGroupLeftBtn = styled(TabButton)` - border-radius: ${({theme}) => theme.border_radius_mix.left}; + border-radius: ${({ theme }) => theme.border_radius_mix.left}; `; export const AddBtn = styled(Button)` width: 160px; - height: 40px; - font-size: ${({theme}) => theme.fontSizes.xs}; + height: ${({ theme }) => theme.buttonHeights.base}; + font-size: ${({ theme }) => theme.fontSizes.xs}; font-weight: bold; background-color: ${({ theme }) => theme.colors.blue}; color: ${({ theme }) => theme.grayScale.off_white}; @@ -37,7 +44,7 @@ export const AddBtn = styled(Button)` export const StyledLoginButton = styled(Button)` width: 340px; - height: 64px; + height: ${({ theme }) => theme.buttonHeights.lg}; font-size: ${({ theme }) => theme.fontSizes.base}; background-color: ${({ theme }) => theme.grayScale.title_active}; color: ${({ theme }) => theme.grayScale.off_white}; diff --git a/frontend/src/styles/theme.js b/frontend/src/styles/theme.js index 5cf279ac0..5040ecb78 100644 --- a/frontend/src/styles/theme.js +++ b/frontend/src/styles/theme.js @@ -1,12 +1,24 @@ import { css } from "styled-components"; -const calcRem = (size) => `${size / 16}rem`; +const calcRem = size => `${size / 16}rem`; const StyledSpaceBetween = css` display: flex; justify-content: space-between; `; +const buttonWidths = { + small: "100px", + base: "128px", + lg: "160px", + xl: "340px", +}; +const buttonHeights = { + small: "28px", + base: "40px", + lg: "64px", +}; + const fontSizes = { xs: calcRem(13), small: calcRem(14), @@ -65,6 +77,7 @@ const border_radius = { const border_radius_mix = { right: "0 11px 11px 0", left: "11px 0 0 11px", + all: "11px", }; const grayScale = { title_active: "#14142B", @@ -113,6 +126,8 @@ const theme = { interval, verticalInterval, StyledSpaceBetween, + buttonWidths, + buttonHeights, }; export default theme; From 2a1736a0caf90e15b0d361588c1808023aff8afa Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Mon, 14 Jun 2021 23:29:56 +0900 Subject: [PATCH 10/71] =?UTF-8?q?refactor:=20=20MyRecoil=20entry=20point?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1(PR=20Review=20=EB=B0=98=EC=98=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/MyRecoil/atom.js | 12 +++-- frontend/src/MyRecoil/index.js | 86 ++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 frontend/src/MyRecoil/index.js diff --git a/frontend/src/MyRecoil/atom.js b/frontend/src/MyRecoil/atom.js index 6c751256c..8f4a4469f 100644 --- a/frontend/src/MyRecoil/atom.js +++ b/frontend/src/MyRecoil/atom.js @@ -1,7 +1,8 @@ -function atom({ key, initialState }) { - return { key, initialState }; -} +// function atom({ key, initialState }) { +// return { key, initialState }; +// } +import { atom } from "./index"; export const issueAtomState = atom({ key: "issueAtomState", initialState: true, @@ -26,3 +27,8 @@ export const authorAtomState = atom({ key: "authorAtomState", initialState: [], }); + +export const clickedFilterAtomState = atom({ + key: "clickedFilterAtomState", + initialState: null, +}); diff --git a/frontend/src/MyRecoil/index.js b/frontend/src/MyRecoil/index.js new file mode 100644 index 000000000..63cb6411a --- /dev/null +++ b/frontend/src/MyRecoil/index.js @@ -0,0 +1,86 @@ +import { useContext, useState, useCallback, useEffect } from "react"; +import { globalStateRoot } from "App"; + +export const atom = ({ key, initialState }) => { + return { key, initialState }; +}; + +export const useRecoilState = atom => { + const { key } = atom; + const store = useContext(globalStateRoot).current; + const [, setReRender] = useState({}); + store.setInitState(atom); + + const forceUpdate = useCallback(() => { + console.log("forced Update"); + setReRender({}); + }, []); + + useEffect(() => { + store.subscribe({ key, fn: forceUpdate }); + }, []); + + return [store.getState(key), store.setState(key)]; +}; +export const useRecoilValue = atom => { + const { key } = atom; + const store = useContext(globalStateRoot).current; + const [, setReRender] = useState({}); + store.setInitState(atom); + + const forceUpdate = useCallback(() => { + console.log("forced Update"); + setReRender({}); + }, []); + + useEffect(() => { + store.subscribe({ key, fn: forceUpdate }); + }, []); + + return store.getState(key); +}; + +export const useSetRecoilState = atom => { + const { key } = atom; + const store = useContext(globalStateRoot).current; + const [, setReRender] = useState({}); + store.setInitState(atom); + + const forceUpdate = useCallback(() => { + console.log("forced Update"); + setReRender({}); + }, []); + + useEffect(() => { + store.subscribe({ key, fn: forceUpdate }); + }, []); + + return store.setState(key); +}; + +export const store = { + observers: {}, + state: {}, + subscribe({ key, fn }) { + this.observers[key] = this.observers[key] || []; + this.observers[key].push(fn); + }, + + setInitState({ key, initialState }) { + if (this.state[key]) return; + this.state[key] = initialState; + }, + + getState(key) { + return this.state[key]; + }, + + setState(key) { + return fn => { + this.state[key] = fn(this.state[key]); + this.observers[key].forEach(callback => callback()); + }; + }, +}; + +export default store; From 594693f30d9ea92f400dd65e4b969f590b49dad5 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Mon, 14 Jun 2021 23:32:42 +0900 Subject: [PATCH 11/71] =?UTF-8?q?feat:=20=EC=84=A0=ED=83=9D=EB=90=9C=20fil?= =?UTF-8?q?ter=EC=9D=98=20filterModal=20=EB=B3=B4=EC=97=AC=EC=A3=BC?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=99=84=EC=84=B1(#29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Issues/IssueList/IssuesHeader.jsx | 70 +++++++++++---- .../components/Issues/Menu/MenuFilterBar.jsx | 33 ++++--- .../src/components/common/FilterModal.jsx | 87 ++++++++++++++----- frontend/src/components/pages/MainPage.jsx | 6 +- frontend/src/data.js | 15 ++++ frontend/src/images/radio_button_checked.svg | 4 + frontend/src/images/radio_button_default.svg | 3 + 7 files changed, 162 insertions(+), 56 deletions(-) create mode 100644 frontend/src/images/radio_button_checked.svg create mode 100644 frontend/src/images/radio_button_default.svg diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index 0bcb768b1..9a7882289 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -4,16 +4,52 @@ import { ReactComponent as Archive } from "images/archive.svg"; import { ReactComponent as Alert } from "images/alert-circle.svg"; import { ReactComponent as DownArrow } from "images/chevron_down.svg"; import theme from "styles/theme"; -import { useEffect } from "react"; +import { useEffect, useCallback } from "react"; +import DropDownButton from "components/common/DropDownButton"; +import FilterModal from "components/common/FilterModal"; +import { filter } from "data"; +import { clickedFilterAtomState } from "MyRecoil/atom"; +import { useRecoilState } from "MyRecoil"; +const buttonNames = ["담당자", "레이블", "마일스톤", "작성자"]; const IssuesHeader = ({}) => { const [isIssueOpenFilter, setIsIssueOpenFilter] = useState(true); // means issueOpen clicked const [isIssueSelected, setIsIssueSelected] = useState(false); // 상태 위치 협의 후 수정 const [isAllIssueSelected, setIsAllIssueSelected] = useState(false); + const [clickedFilter, setClickedFilter] = useState(""); const checkAllIssue = () => { setIsAllIssueSelected(!isAllIssueSelected); }; + //----------중복 코드from MeuFilter -------- + const [isFilterClicked, setIsFilterClicked] = useState(false); + const handleClick = useCallback(e => { + isFilterClicked === false + ? setIsFilterClicked(true) + : setIsFilterClicked(false); + console.dir(e.target.textContent); + console.dir(e.target); + setClickedFilter(e.target.textContent); + }); + + useEffect(() => { + window.addEventListener("click", closeFilterModal); + return function cleanup() { + window.removeEventListener("click", closeFilterModal); + }; + }, [isFilterClicked]); + + const closeFilterModal = e => { + const target = e.target; + if ( + isFilterClicked && + !target.closest(".filter-modal") && + !target.closest(".issue-header-button") + ) + setIsFilterClicked(false); + }; + //----------여기 까지 중복 코드from MeuFilter --------/ + useEffect(() => { isAllIssueSelected && console.log("issue checkbox all selected"); }, [isAllIssueSelected]); @@ -42,20 +78,21 @@ const IssuesHeader = ({}) => { ) : ( - 담당자 - - - - 레이블 - - - - 마일스톤 - - - - 작성자 - + {buttonNames.map((filter, idx) => ( + theme.buttonWidths.small} + border={"none"} + id={filter} + > + ))} + {isFilterClicked && } + {/* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state props로 내림 */} + {/* 🔥recoil로 수정 필요 */} + {/* 🔥회살표 클릭해도 필터 제대로 뜨도록 수정필요 */} )} @@ -93,8 +130,9 @@ const OpenCloseEdit = styled.div` const FiltersWrapper = styled.div` display: flex; - width: 500px; justify-content: space-around; + position: relative; + /* outline: red 1px solid; */ `; export const CheckBox = styled.div` diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index cc99f5c21..a9b521185 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -3,33 +3,40 @@ import { ReactComponent as SearchIcon } from "images/search.svg"; import DropDownButton from "components/common/DropDownButton"; import theme from "styles/theme"; import FilterModal from "components/common/FilterModal"; -import { useState, useEffect } from "react"; +import { useState, useEffect, useCallback } from "react"; +import { filter } from "data"; const MenuFilterBar = () => { - const [isFilterClicked, setIsFilterClicked] = useState(false); //isFilterClicked말고 flag에 쓸만한 이름 추천좀.. - const handleClick = () => { + const [isFilterClicked, setIsFilterClicked] = useState(false); + const [clickedFilter, setClickedFilter] = useState(""); + const handleClick = useCallback(e => { isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); - }; - //토글 하면됨 + setClickedFilter(e.target.textContent); + }); useEffect(() => { - document.body.addEventListener("click", closePopup); + window.addEventListener("click", closeFilterModal); return function cleanup() { - window.removeEventListener("click", closePopup); + window.removeEventListener("click", closeFilterModal); }; - }, []); + }, [isFilterClicked]); - const closePopup = e => { + const closeFilterModal = e => { const target = e.target; - // console.log(target); - !target.closest(".filter-modal") && setIsFilterClicked(false); + if (isFilterClicked && !target.closest(".filter-modal")) + setIsFilterClicked(false); }; return ( <> - + theme.buttonWidths.base} + radius={"left"} + /> @@ -37,7 +44,7 @@ const MenuFilterBar = () => { - {} + {isFilterClicked && } ); }; diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index 980bfd3fb..fc71d4a1a 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -5,51 +5,76 @@ import FormControl from "@material-ui/core/FormControl"; import FormLabel from "@material-ui/core/FormLabel"; import { useState } from "react"; import styled from "styled-components"; -const data = [ - "열린 이슈", - "내가 작성한 이슈", - "나에게 할당한 이슈", - "나에게 할당된 이슈", - "내가 댓글을 남긴 이슈", - "닫힌 이슈", -]; -//디자인 수정 필요 -const FilterModal = () => { - const [value, setValue] = useState("female"); +import { filter } from "data"; + +{ + /* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state내림 */ +} +const FilterModal = ({ filterType }) => { + const [value, setValue] = useState(""); + + // Recoil로직 (구현 예정) + // 1. 필터별로 선택된 필터는 atom으로 관리됨(default는 null임) + // 2. 이슈리스트 필터링, 검색창에 현재 선택된 필터들 보여줄 때는 그 Atom의 조합으로 보여줌 (특히 검색창엔 selector이용해서 붙이면 간단할듯) const handleChange = event => { setValue(event.target.value); - console.log(event.target.value); }; + const getFilterModalData = type => { + switch (type) { + case "담당자": { + return filter.assignee; + } + case "레이블": { + return filter.label; + } + case "마일스톤": { + return filter.milestone; + } + case "작성자": { + return filter.author; + } + case "필터": { + return filter.issue; + } + } + }; + const filterData = getFilterModalData(filterType); return ( - 이슈 필터 - + {filterType === "필터" && ""} 필터 + + - {data.map(x => ( - } - label={x} - labelPlacement="start" - /> - ))} - + {filterData && + filterData.map((x, idx) => ( + } + label={x} + labelPlacement="start" + key={idx} + /> + ))} + ); }; const FilterModalLayout = styled.div` position: absolute; - top: 100%; + top: 110%; background-color: white; text-align: left; + border-radius: 16px; + border: 1px solid ${({ theme }) => theme.grayScale.line}; `; const FilterControlLabel = styled(FormControlLabel)` @@ -58,4 +83,18 @@ const FilterControlLabel = styled(FormControlLabel)` margin: 0; `; +const FilterRadioContainer = styled(RadioGroup)` + padding: 8px 16px; +`; +const FilterTitle = styled(FormLabel)` + background-color: ${({ theme }) => theme.grayScale.background}; + width: 100%; + border-bottom: 1px solid ${({ theme }) => theme.grayScale.line}; + border-radius: 16px 16px 0px 0px; + padding: 8px 16px; + font-size: 18px; + color: ${({ theme }) => theme.grayScale.title_active}; + line-height: 32px; +`; + export default FilterModal; diff --git a/frontend/src/components/pages/MainPage.jsx b/frontend/src/components/pages/MainPage.jsx index 6900eea12..16f825a77 100644 --- a/frontend/src/components/pages/MainPage.jsx +++ b/frontend/src/components/pages/MainPage.jsx @@ -18,17 +18,17 @@ const MainPage = () => { return localStorage.getItem("accessToken") ? (
- + {/* */} {(pathname === "/main/labels" || pathname === "/main/milestones") && ( )} {pathname === "/main" && } - + {/* */} - + {/* */} diff --git a/frontend/src/data.js b/frontend/src/data.js index 61f8e22e8..39825d8f7 100644 --- a/frontend/src/data.js +++ b/frontend/src/data.js @@ -18,3 +18,18 @@ export const issues = [ isOpen: false, }, ]; + +export const filter = { + issue: [ + "열린 이슈", + "내가 작성한 이슈", + "나에게 할당한 이슈", + "나에게 할당된 이슈", + "내가 댓글을 남긴 이슈", + "닫힌 이슈", + ], + assignee: ["daisy", "goody"], + label: ["bug", "document"], + milestone: ["마일스톤이 없는 필터", "마스터즈 코스"], + author: ["daisy", "goody"], +}; diff --git a/frontend/src/images/radio_button_checked.svg b/frontend/src/images/radio_button_checked.svg new file mode 100644 index 000000000..c6bdba5dd --- /dev/null +++ b/frontend/src/images/radio_button_checked.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/src/images/radio_button_default.svg b/frontend/src/images/radio_button_default.svg new file mode 100644 index 000000000..6af3ac93d --- /dev/null +++ b/frontend/src/images/radio_button_default.svg @@ -0,0 +1,3 @@ + + + From 932136c7f9bcf1c617725d3d769f0e3679fa0db7 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Tue, 15 Jun 2021 11:25:36 +0900 Subject: [PATCH 12/71] =?UTF-8?q?style:=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=A3=BC=EC=84=9D=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.jsx | 13 +- frontend/src/MyRecoil/atom.js | 64 +++---- frontend/src/MyRecoil/index.js | 172 +++++++++--------- frontend/src/MyRecoil/store.js | 26 --- frontend/src/MyRecoil/useRecoilState.js | 19 -- frontend/src/MyRecoil/useRecoilValue.js | 20 -- frontend/src/MyRecoil/useSetRecoilState.js | 20 -- frontend/src/RecoilStore/Atoms.jsx | 20 +- .../components/Issues/IssueList/IssueCard.jsx | 24 +-- .../components/Issues/IssueList/IssueList.jsx | 39 +--- .../Issues/IssueList/IssuesHeader.jsx | 53 ++---- 11 files changed, 169 insertions(+), 301 deletions(-) delete mode 100644 frontend/src/MyRecoil/store.js delete mode 100644 frontend/src/MyRecoil/useRecoilState.js delete mode 100644 frontend/src/MyRecoil/useRecoilValue.js delete mode 100644 frontend/src/MyRecoil/useSetRecoilState.js diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index c8da29701..5e981514b 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -11,14 +11,14 @@ import Labels from "./components/Labels/Labels"; import NewIssue from "./components/pages/NewIssuePage"; import { ThemeProvider } from "styled-components"; import theme from "styles/theme"; -import store from "./MyRecoil/store"; - -export const globalStateRoot = createContext(); +// import store from "./MyRecoil"; +// export const globalStateRoot = createContext(); function App() { - const globalState = useRef(store); + // const globalState = useRef(store); return ( - + // + @@ -30,7 +30,8 @@ function App() { - + + // {/* */} ); } diff --git a/frontend/src/MyRecoil/atom.js b/frontend/src/MyRecoil/atom.js index db04459d7..75b36f254 100644 --- a/frontend/src/MyRecoil/atom.js +++ b/frontend/src/MyRecoil/atom.js @@ -1,39 +1,39 @@ -// function atom({ key, initialState }) { -// return { key, initialState }; -// } +// // function atom({ key, initialState }) { +// // return { key, initialState }; +// // } -import { atom } from "./index"; -export const issueAtomState = atom({ - key: "issueAtomState", - initialState: true, -}); +// import { atom } from "./index"; +// export const issueAtomState = atom({ +// key: "issueAtomState", +// initialState: true, +// }); -export const milestoneAtomState = atom({ - key: "milestoneAtomState", - initialState: [], -}); +// export const milestoneAtomState = atom({ +// key: "milestoneAtomState", +// initialState: [], +// }); -export const asigneeAtomState = atom({ - key: "asigneeAtomState", - initialState: [], -}); +// export const asigneeAtomState = atom({ +// key: "asigneeAtomState", +// initialState: [], +// }); -export const labelAtomState = atom({ - key: "labelAtomState", - initialState: [], -}); +// export const labelAtomState = atom({ +// key: "labelAtomState", +// initialState: [], +// }); -export const authorAtomState = atom({ - key: "authorAtomState", - initialState: [], -}); +// export const authorAtomState = atom({ +// key: "authorAtomState", +// initialState: [], +// }); -export const selectedIssueCntAtomState = atom({ - key: "selectedIssueCntAtomState", - initialState: 0, - )}; +// export const selectedIssueCntAtomState = atom({ +// key: "selectedIssueCntAtomState", +// initialState: 0, +// }); -export const clickedFilterAtomState = atom({ - key: "clickedFilterAtomState", - initialState: null, -}); +// export const clickedFilterAtomState = atom({ +// key: "clickedFilterAtomState", +// initialState: null, +// }); diff --git a/frontend/src/MyRecoil/index.js b/frontend/src/MyRecoil/index.js index 63cb6411a..765821a97 100644 --- a/frontend/src/MyRecoil/index.js +++ b/frontend/src/MyRecoil/index.js @@ -1,86 +1,86 @@ -import { useContext, useState, useCallback, useEffect } from "react"; -import { globalStateRoot } from "App"; - -export const atom = ({ key, initialState }) => { - return { key, initialState }; -}; - -export const useRecoilState = atom => { - const { key } = atom; - const store = useContext(globalStateRoot).current; - const [, setReRender] = useState({}); - store.setInitState(atom); - - const forceUpdate = useCallback(() => { - console.log("forced Update"); - setReRender({}); - }, []); - - useEffect(() => { - store.subscribe({ key, fn: forceUpdate }); - }, []); - - return [store.getState(key), store.setState(key)]; -}; -export const useRecoilValue = atom => { - const { key } = atom; - const store = useContext(globalStateRoot).current; - const [, setReRender] = useState({}); - store.setInitState(atom); - - const forceUpdate = useCallback(() => { - console.log("forced Update"); - setReRender({}); - }, []); - - useEffect(() => { - store.subscribe({ key, fn: forceUpdate }); - }, []); - - return store.getState(key); -}; - -export const useSetRecoilState = atom => { - const { key } = atom; - const store = useContext(globalStateRoot).current; - const [, setReRender] = useState({}); - store.setInitState(atom); - - const forceUpdate = useCallback(() => { - console.log("forced Update"); - setReRender({}); - }, []); - - useEffect(() => { - store.subscribe({ key, fn: forceUpdate }); - }, []); - - return store.setState(key); -}; - -export const store = { - observers: {}, - state: {}, - subscribe({ key, fn }) { - this.observers[key] = this.observers[key] || []; - this.observers[key].push(fn); - }, - - setInitState({ key, initialState }) { - if (this.state[key]) return; - this.state[key] = initialState; - }, - - getState(key) { - return this.state[key]; - }, - - setState(key) { - return fn => { - this.state[key] = fn(this.state[key]); - this.observers[key].forEach(callback => callback()); - }; - }, -}; - -export default store; +// import { useContext, useState, useCallback, useEffect } from "react"; +// import { globalStateRoot } from "App"; + +// export const atom = ({ key, initialState }) => { +// return { key, initialState }; +// }; + +// export const useRecoilState = atom => { +// const { key } = atom; +// const store = useContext(globalStateRoot).current; +// const [, setReRender] = useState({}); +// store.setInitState(atom); + +// const forceUpdate = useCallback(() => { +// console.log("forced Update"); +// setReRender({}); +// }, []); + +// useEffect(() => { +// store.subscribe({ key, fn: forceUpdate }); +// }, []); + +// return [store.getState(key), store.setState(key)]; +// }; +// export const useRecoilValue = atom => { +// const { key } = atom; +// const store = useContext(globalStateRoot).current; +// const [, setReRender] = useState({}); +// store.setInitState(atom); + +// const forceUpdate = useCallback(() => { +// console.log("forced Update"); +// setReRender({}); +// }, []); + +// useEffect(() => { +// store.subscribe({ key, fn: forceUpdate }); +// }, []); + +// return store.getState(key); +// }; + +// export const useSetRecoilState = atom => { +// const { key } = atom; +// const store = useContext(globalStateRoot).current; +// const [, setReRender] = useState({}); +// store.setInitState(atom); + +// const forceUpdate = useCallback(() => { +// console.log("forced Update"); +// setReRender({}); +// }, []); + +// useEffect(() => { +// store.subscribe({ key, fn: forceUpdate }); +// }, []); + +// return store.setState(key); +// }; + +// export const store = { +// observers: {}, +// state: {}, +// subscribe({ key, fn }) { +// this.observers[key] = this.observers[key] || []; +// this.observers[key].push(fn); +// }, + +// setInitState({ key, initialState }) { +// if (this.state[key]) return; +// this.state[key] = initialState; +// }, + +// getState(key) { +// return this.state[key]; +// }, + +// setState(key) { +// return fn => { +// this.state[key] = fn(this.state[key]); +// this.observers[key].forEach(callback => callback()); +// }; +// }, +// }; + +// export default store; diff --git a/frontend/src/MyRecoil/store.js b/frontend/src/MyRecoil/store.js deleted file mode 100644 index 84fd34f74..000000000 --- a/frontend/src/MyRecoil/store.js +++ /dev/null @@ -1,26 +0,0 @@ -const store = { - observers: {}, - state: {}, - subscribe({ key, fn }) { - this.observers[key] = this.observers[key] || []; - this.observers[key].push(fn); - }, - - setInitState({ key, initialState }) { - if (this.state[key]) return; - this.state[key] = initialState; - }, - - getState(key) { - return this.state[key]; - }, - - setState(key) { - return fn => { - this.state[key] = fn(this.state[key]); - this.observers[key].forEach(callback => callback()); - }; - }, -}; - -export default store; diff --git a/frontend/src/MyRecoil/useRecoilState.js b/frontend/src/MyRecoil/useRecoilState.js deleted file mode 100644 index c88d34c4b..000000000 --- a/frontend/src/MyRecoil/useRecoilState.js +++ /dev/null @@ -1,19 +0,0 @@ -import { useContext, useState, useCallback, useEffect } from "react"; -import { globalStateRoot } from "App"; - -export const useRecoilState = atom => { - const { key } = atom; - const store = useContext(globalStateRoot).current; - const [, setReRender] = useState({}); - store.setInitState(atom); - - const forceUpdate = useCallback(() => { - setReRender({}); - }, []); - - useEffect(() => { - store.subscribe({ key, fn: forceUpdate }); - }, []); - - return [store.getState(key), store.setState(key)]; -}; diff --git a/frontend/src/MyRecoil/useRecoilValue.js b/frontend/src/MyRecoil/useRecoilValue.js deleted file mode 100644 index 84e664981..000000000 --- a/frontend/src/MyRecoil/useRecoilValue.js +++ /dev/null @@ -1,20 +0,0 @@ -import { useContext, useState, useCallback, useEffect } from "react"; -import { globalStateRoot } from "App"; - -export const useRecoilValue = atom => { - const { key } = atom; - const store = useContext(globalStateRoot).current; - const [, setReRender] = useState({}); - store.setInitState(atom); - - const forceUpdate = useCallback(() => { - console.log("forced Update"); - setReRender({}); - }, []); - - useEffect(() => { - store.subscribe({ key, fn: forceUpdate }); - }, []); - - return store.getState(key); -}; diff --git a/frontend/src/MyRecoil/useSetRecoilState.js b/frontend/src/MyRecoil/useSetRecoilState.js deleted file mode 100644 index 6808ce1ab..000000000 --- a/frontend/src/MyRecoil/useSetRecoilState.js +++ /dev/null @@ -1,20 +0,0 @@ -import { useContext, useState, useCallback, useEffect } from "react"; -import { globalStateRoot } from "App"; - -export const useSetRecoilState = atom => { - const { key } = atom; - const store = useContext(globalStateRoot).current; - const [, setReRender] = useState({}); - store.setInitState(atom); - - const forceUpdate = useCallback(() => { - console.log("forced Update"); - setReRender({}); - }, []); - - useEffect(() => { - store.subscribe({ key, fn: forceUpdate }); - }, []); - - return store.setState(key); -}; diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 9bfcf9173..2dcf51c09 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -1,26 +1,36 @@ import { atom } from "recoil"; export const issueAtomState = atom({ - key: "issueFilter", + key: "issueAtomState", default: "열린 이슈", }); export const assigneeAtomState = atom({ - key: "assigneeFilter", + key: "assigneeAtomState", default: [], }); export const labelAtomState = atom({ - key: "labelFilter", + key: "labelAtomState", default: [], }); export const milestoneAtomState = atom({ - key: "milestoneFilter", + key: "milestoneAtomState", default: [], }); export const authorAtomState = atom({ - key: "authorFilter", + key: "authorAtomState", default: [], }); + +export const selectedIssueCntAtomState = atom({ + key: "selectedIssueCntAtomState", + initialState: 0, +}); + +export const clickedFilterAtomState = atom({ + key: "clickedFilterAtomState", + initialState: null, +}); diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index b0a80ed37..63b232cf0 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -6,23 +6,14 @@ import { ReactComponent as UserImageSmall } from "images/UserImageSmall.svg"; import { ReactComponent as Alert } from "images/alert-circle.svg"; import { ReactComponent as Milestone } from "images/milestone.svg"; import getTimeStamp from "util/getTimeStamp"; -import { useRecoilState } from "MyRecoil/useRecoilState"; -import { selectedIssueCntAtomState } from "MyRecoil/atom"; +// import { useRecoilState } from "MyRecoil"; +// import { selectedIssueCntAtomState } from "MyRecoil/atom"; +import { selectedIssueCntAtomState } from "RecoilStore/Atoms"; +import { useRecoilState } from "recoil"; -const IssueCard = ({ - issue, - setIsAnyIssueSelected, - isAllIssueSelected, - setIsAllIssueSelected, - initCheck, - setInitCheck, - selectedCards, - setSelectedCards, -}) => { +const IssueCard = ({ issue, setIsAnyIssueSelected, isAllIssueSelected, setIsAllIssueSelected, initCheck, setInitCheck, selectedCards, setSelectedCards }) => { const [isChecked, setIsChecked] = useState(false); - const [selectedIssues, setSelectedIssues] = useRecoilState( - selectedIssueCntAtomState - ); + const [selectedIssues, setSelectedIssues] = useRecoilState(selectedIssueCntAtomState); // const [initCheck, setInitCheck] = useState(true); const { title, id, labelId, milestoneId, author, createdAt } = issue; const handleCheck = () => { @@ -66,8 +57,7 @@ const IssueCard = ({ #{id} - 이 이슈가 {getTimeStamp(createdAt)}, {author}님에 의해 - 작성되었습니다 + 이 이슈가 {getTimeStamp(createdAt)}, {author}님에 의해 작성되었습니다 diff --git a/frontend/src/components/Issues/IssueList/IssueList.jsx b/frontend/src/components/Issues/IssueList/IssueList.jsx index 139af58ee..b33492bef 100644 --- a/frontend/src/components/Issues/IssueList/IssueList.jsx +++ b/frontend/src/components/Issues/IssueList/IssueList.jsx @@ -3,8 +3,10 @@ import styled from "styled-components"; import IssuesHeader from "./IssuesHeader"; import IssueCard from "./IssueCard"; import { issues } from "data"; -import { selectedIssueCntAtomState } from "MyRecoil/atom"; -import { useRecoilState } from "MyRecoil/useRecoilState"; +// import { selectedIssueCntAtomState } from "MyRecoil/atom"; +import { useRecoilState } from "recoil"; +import { selectedIssueCntAtomState } from "RecoilStore/Atoms"; +// import { useRecoilState } from "MyRecoil"; const IssueList = () => { const [isAnyIssueSelected, setIsAnyIssueSelected] = useState(false); // 상태 위치 협의 후 수정 @@ -14,40 +16,15 @@ const IssueList = () => { const [selectedCards, setSelectedCards] = useState(new Set()); useEffect(() => { - if (!initCheck && !isAllIssueSelected && !isAnyIssueSelected) - setSelectedIssues(() => 0); + if (!initCheck && !isAllIssueSelected && !isAnyIssueSelected) setSelectedIssues(() => 0); }, [isAnyIssueSelected]); - const issueList = issues.map(issue => ( - - )); + const issueList = issues.map((issue) => ); return ( - - {issueList.length ? ( - issueList - ) : ( - 검색과 일치하는 결과가 없습니다 - )} + + {issueList.length ? issueList : 검색과 일치하는 결과가 없습니다} ); }; diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index a05bcbc72..be704ed87 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -8,24 +8,15 @@ import DropDownButton from "components/common/DropDownButton"; import FilterModal from "components/common/FilterModal"; import { filter } from "data"; +// import { selectedIssueCntAtomState, clickedFilterAtomState } from "MyRecoil/atom"; +// import { useRecoilState } from "MyRecoil"; +import { useRecoilState } from "recoil"; +import { selectedIssueCntAtomState, clickedFilterAtomState } from "RecoilStore/Atoms"; -import { selectedIssueCntAtomState, clickedFilterAtomState } from "MyRecoil/atom"; -import { useRecoilState } from "MyRecoil"; - -const IssuesHeader = ({ - isAnyIssueSelected, - setIsAnyIssueSelected, - isAllIssueSelected, - setIsAllIssueSelected, - issuesCnt, - initCheck, - setInitCheck, -}) => { - const [selectedIssues, setSelectedIssues] = useRecoilState( - selectedIssueCntAtomState - ); -const buttonNames = ["담당자", "레이블", "마일스톤", "작성자"]; -const [clickedFilter, setClickedFilter] = useState(""); +const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSelected, setIsAllIssueSelected, issuesCnt, initCheck, setInitCheck }) => { + const [selectedIssues, setSelectedIssues] = useRecoilState(selectedIssueCntAtomState); + const buttonNames = ["담당자", "레이블", "마일스톤", "작성자"]; + const [clickedFilter, setClickedFilter] = useState(""); const checkAllIssue = () => { setIsAllIssueSelected(!isAllIssueSelected); @@ -33,10 +24,8 @@ const [clickedFilter, setClickedFilter] = useState(""); //----------중복 코드from MeuFilter -------- const [isFilterClicked, setIsFilterClicked] = useState(false); - const handleClick = useCallback(e => { - isFilterClicked === false - ? setIsFilterClicked(true) - : setIsFilterClicked(false); + const handleClick = useCallback((e) => { + isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); console.dir(e.target.textContent); console.dir(e.target); setClickedFilter(e.target.textContent); @@ -49,14 +38,9 @@ const [clickedFilter, setClickedFilter] = useState(""); }; }, [isFilterClicked]); - const closeFilterModal = e => { + const closeFilterModal = (e) => { const target = e.target; - if ( - isFilterClicked && - !target.closest(".filter-modal") && - !target.closest(".issue-header-button") - ) - setIsFilterClicked(false); + if (isFilterClicked && !target.closest(".filter-modal") && !target.closest(".issue-header-button")) setIsFilterClicked(false); }; //----------여기 까지 중복 코드from MeuFilter --------/ @@ -74,8 +58,7 @@ const [clickedFilter, setClickedFilter] = useState(""); useEffect(() => { if (selectedIssues === 0) setIsAnyIssueSelected(false); - if (isAllIssueSelected && selectedIssues === 1) - setIsAnyIssueSelected(false); + if (isAllIssueSelected && selectedIssues === 1) setIsAnyIssueSelected(false); }, [selectedIssues]); return ( @@ -111,15 +94,7 @@ const [clickedFilter, setClickedFilter] = useState(""); {buttonNames.map((filter, idx) => ( - theme.buttonWidths.small} - border={"none"} - id={filter} - > + theme.buttonWidths.small} border={"none"} id={filter}> ))} {isFilterClicked && } {/* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state props로 내림 */} From 939380bd88afb2dac5004ff157adb0c8493eac07 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Tue, 15 Jun 2021 13:50:53 +0900 Subject: [PATCH 13/71] =?UTF-8?q?fix:=20=EC=B2=B4=ED=81=AC=EB=B0=95?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 29 ++----------------- .../components/Issues/IssueList/IssueCard.jsx | 20 ++++--------- .../Issues/IssueList/IssuesHeader.jsx | 29 +++++-------------- frontend/src/index.jsx | 1 - 4 files changed, 15 insertions(+), 64 deletions(-) diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 2dcf51c09..7bfba9033 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -1,36 +1,11 @@ import { atom } from "recoil"; -export const issueAtomState = atom({ - key: "issueAtomState", - default: "열린 이슈", -}); - -export const assigneeAtomState = atom({ - key: "assigneeAtomState", - default: [], -}); - -export const labelAtomState = atom({ - key: "labelAtomState", - default: [], -}); - -export const milestoneAtomState = atom({ - key: "milestoneAtomState", - default: [], -}); - -export const authorAtomState = atom({ - key: "authorAtomState", - default: [], -}); - export const selectedIssueCntAtomState = atom({ key: "selectedIssueCntAtomState", - initialState: 0, + default: 0, }); export const clickedFilterAtomState = atom({ key: "clickedFilterAtomState", - initialState: null, + default: null, }); diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index 63b232cf0..a69f7e95c 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -14,29 +14,19 @@ import { useRecoilState } from "recoil"; const IssueCard = ({ issue, setIsAnyIssueSelected, isAllIssueSelected, setIsAllIssueSelected, initCheck, setInitCheck, selectedCards, setSelectedCards }) => { const [isChecked, setIsChecked] = useState(false); const [selectedIssues, setSelectedIssues] = useRecoilState(selectedIssueCntAtomState); - // const [initCheck, setInitCheck] = useState(true); const { title, id, labelId, milestoneId, author, createdAt } = issue; const handleCheck = () => { setIsChecked(!isChecked); + isChecked ? setSelectedIssues(selectedIssues - 1) : setSelectedIssues(selectedIssues + 1); }; useEffect(() => { - if (isAllIssueSelected) { - setIsChecked(true); - } else if (!isAllIssueSelected) setIsChecked(false); - }, [isAllIssueSelected]); + isChecked ? setIsAnyIssueSelected(true) : setIsAnyIssueSelected(false); + }, [isChecked]); useEffect(() => { - if (isChecked) { - setIsAnyIssueSelected(true); - setSelectedIssues(() => selectedIssues + 1); - setInitCheck(false); - setSelectedCards(() => selectedCards.add(id)); - } else if (!initCheck && !isChecked) { - setSelectedIssues(() => selectedIssues - 1); - selectedCards.delete(id); - } - }, [isChecked]); + isAllIssueSelected ? setIsChecked(true) : setIsChecked(false); + }, [isAllIssueSelected]); return ( diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index be704ed87..de80a3765 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -18,10 +18,6 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel const buttonNames = ["담당자", "레이블", "마일스톤", "작성자"]; const [clickedFilter, setClickedFilter] = useState(""); - const checkAllIssue = () => { - setIsAllIssueSelected(!isAllIssueSelected); - }; - //----------중복 코드from MeuFilter -------- const [isFilterClicked, setIsFilterClicked] = useState(false); const handleClick = useCallback((e) => { @@ -44,21 +40,16 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel }; //----------여기 까지 중복 코드from MeuFilter --------/ - useEffect(() => { - if (isAllIssueSelected) { - setIsAnyIssueSelected(true); - setInitCheck(false); - setSelectedIssues(() => issuesCnt); - } - if (!initCheck && !isAllIssueSelected) { - setIsAnyIssueSelected(false); - setSelectedIssues(() => 0); - } - }, [isAllIssueSelected]); + const checkAllIssue = () => { + setIsAllIssueSelected(!isAllIssueSelected); + isAllIssueSelected ? setSelectedIssues(0) : setSelectedIssues(issuesCnt); + }; + + console.log(`selectedIssues: ${selectedIssues}, isAnyissueSelected: ${isAnyIssueSelected}`); useEffect(() => { if (selectedIssues === 0) setIsAnyIssueSelected(false); - if (isAllIssueSelected && selectedIssues === 1) setIsAnyIssueSelected(false); + else setIsAnyIssueSelected(true); }, [selectedIssues]); return ( @@ -67,11 +58,7 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel {isAnyIssueSelected ? ( - isAllIssueSelected ? ( -
{selectedIssues - 1}개 이슈 선택
- ) : ( -
{selectedIssues}개 이슈 선택
- ) +
{selectedIssues}개 이슈 선택
) : ( diff --git a/frontend/src/index.jsx b/frontend/src/index.jsx index d18290f78..14612e910 100644 --- a/frontend/src/index.jsx +++ b/frontend/src/index.jsx @@ -5,7 +5,6 @@ import App from "./App"; import { BrowserRouter } from "react-router-dom"; import GlobalStyle from "./styles/GlobalStyle"; import { StylesProvider } from "@material-ui/core/styles"; -import { RecoilRoot } from "recoil"; ReactDOM.render( From fe1fef3e4377c648f2f8783623e85ccd2df4d56d Mon Sep 17 00:00:00 2001 From: junzero741 Date: Tue, 15 Jun 2021 14:58:49 +0900 Subject: [PATCH 14/71] =?UTF-8?q?feat:=20=EC=84=A0=ED=83=9D=EB=90=9C=20?= =?UTF-8?q?=EC=9D=B4=EC=8A=88=20=EC=97=B4=EA=B8=B0/=EB=8B=AB=EA=B8=B0=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Issues/IssueList/IssuesHeader.jsx | 28 +++++++-------- .../src/components/common/FilterModal.jsx | 34 +++++++------------ frontend/src/data.js | 10 ++---- 3 files changed, 28 insertions(+), 44 deletions(-) diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index de80a3765..7c69f1e97 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -73,21 +73,22 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel {isAnyIssueSelected ? ( - 상태 수정 - + theme.buttonWidths.lg} border={"none"}> + {isFilterClicked && } ) : ( - - {buttonNames.map((filter, idx) => ( + {buttonNames.map((filter, idx) => ( + theme.buttonWidths.small} border={"none"} id={filter}> - ))} - {isFilterClicked && } - {/* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state props로 내림 */} - {/* 🔥recoil로 수정 필요 */} - {/* 🔥회살표 클릭해도 필터 제대로 뜨도록 수정필요 */} - + + ))} + + {isFilterClicked && } + {/* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state props로 내림 */} + {/* 🔥recoil로 수정 필요 */} + {/* 🔥회살표 클릭해도 필터 제대로 뜨도록 수정필요 */} )} @@ -120,12 +121,13 @@ const OpenCloseEdit = styled.div` display: flex; width: 200px; justify-content: center; + /* position: relative; */ `; const FiltersWrapper = styled.div` display: flex; justify-content: space-around; - position: relative; + /* position: relative; */ /* outline: red 1px solid; */ `; @@ -135,7 +137,5 @@ export const CheckBox = styled.div` `; const TextIconDivider = styled.div` - display: flex; - justify-content: space-between; - align-items: center; + position: relative; `; diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index fc71d4a1a..30fa7f483 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -12,16 +12,16 @@ import { filter } from "data"; } const FilterModal = ({ filterType }) => { const [value, setValue] = useState(""); - + console.log("filter modal"); // Recoil로직 (구현 예정) // 1. 필터별로 선택된 필터는 atom으로 관리됨(default는 null임) // 2. 이슈리스트 필터링, 검색창에 현재 선택된 필터들 보여줄 때는 그 Atom의 조합으로 보여줌 (특히 검색창엔 selector이용해서 붙이면 간단할듯) - const handleChange = event => { + const handleChange = (event) => { setValue(event.target.value); }; - const getFilterModalData = type => { + const getFilterModalData = (type) => { switch (type) { case "담당자": { return filter.assignee; @@ -38,31 +38,21 @@ const FilterModal = ({ filterType }) => { case "필터": { return filter.issue; } + case "상태 수정": { + return filter.openClose; + } + default: { + console.error("unhandled type"); + } } }; const filterData = getFilterModalData(filterType); return ( - - {filterType === "필터" && ""} 필터 - - - {filterData && - filterData.map((x, idx) => ( - } - label={x} - labelPlacement="start" - key={idx} - /> - ))} + {filterType === "필터" && ""} 필터 + + {filterData && filterData.map((x, idx) => } label={x} labelPlacement="start" key={idx} />)} diff --git a/frontend/src/data.js b/frontend/src/data.js index 77c22ab0c..439bed72b 100644 --- a/frontend/src/data.js +++ b/frontend/src/data.js @@ -20,16 +20,10 @@ export const issues = [ ]; export const filter = { - issue: [ - "열린 이슈", - "내가 작성한 이슈", - "나에게 할당한 이슈", - "나에게 할당된 이슈", - "내가 댓글을 남긴 이슈", - "닫힌 이슈", - ], + issue: ["열린 이슈", "내가 작성한 이슈", "나에게 할당한 이슈", "나에게 할당된 이슈", "내가 댓글을 남긴 이슈", "닫힌 이슈"], assignee: ["daisy", "goody"], label: ["bug", "document"], milestone: ["마일스톤이 없는 필터", "마스터즈 코스"], author: ["daisy", "goody"], + openClose: ["선택된 이슈 열기", "선택된 이슈 닫기"], }; From f12a153fa1442d9f611656bc89f6e24a745fff9d Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Tue, 15 Jun 2021 15:41:19 +0900 Subject: [PATCH 15/71] =?UTF-8?q?fix:=20merge=20=ED=9B=84=20filter=20?= =?UTF-8?q?=EB=B3=84=20modal=20=EB=9C=A8=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0(#29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Issues/IssueList/IssuesHeader.jsx | 72 ++++++++++++++----- .../components/Issues/Menu/MenuFilterBar.jsx | 9 +-- .../src/components/common/FilterModal.jsx | 35 ++++++--- 3 files changed, 86 insertions(+), 30 deletions(-) diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index 7c69f1e97..15ee7e95d 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -10,21 +10,36 @@ import { filter } from "data"; // import { selectedIssueCntAtomState, clickedFilterAtomState } from "MyRecoil/atom"; // import { useRecoilState } from "MyRecoil"; -import { useRecoilState } from "recoil"; -import { selectedIssueCntAtomState, clickedFilterAtomState } from "RecoilStore/Atoms"; - -const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSelected, setIsAllIssueSelected, issuesCnt, initCheck, setInitCheck }) => { - const [selectedIssues, setSelectedIssues] = useRecoilState(selectedIssueCntAtomState); +import { useRecoilState, useSetRecoilState } from "recoil"; +import { + selectedIssueCntAtomState, + clickedFilterAtomState, +} from "RecoilStore/Atoms"; + +const IssuesHeader = ({ + isAnyIssueSelected, + setIsAnyIssueSelected, + isAllIssueSelected, + setIsAllIssueSelected, + issuesCnt, + initCheck, + setInitCheck, +}) => { + const [selectedIssues, setSelectedIssues] = useRecoilState( + selectedIssueCntAtomState + ); const buttonNames = ["담당자", "레이블", "마일스톤", "작성자"]; - const [clickedFilter, setClickedFilter] = useState(""); + const setClickedFilterState = useSetRecoilState(clickedFilterAtomState); //----------중복 코드from MeuFilter -------- const [isFilterClicked, setIsFilterClicked] = useState(false); - const handleClick = useCallback((e) => { - isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); + const handleClick = useCallback(e => { + isFilterClicked === false + ? setIsFilterClicked(true) + : setIsFilterClicked(false); console.dir(e.target.textContent); console.dir(e.target); - setClickedFilter(e.target.textContent); + setClickedFilterState(e.target.textContent); }); useEffect(() => { @@ -34,9 +49,14 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel }; }, [isFilterClicked]); - const closeFilterModal = (e) => { + const closeFilterModal = e => { const target = e.target; - if (isFilterClicked && !target.closest(".filter-modal") && !target.closest(".issue-header-button")) setIsFilterClicked(false); + if ( + isFilterClicked && + !target.closest(".filter-modal") && + !target.closest(".issue-header-button") + ) + setIsFilterClicked(false); }; //----------여기 까지 중복 코드from MeuFilter --------/ @@ -45,7 +65,9 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel isAllIssueSelected ? setSelectedIssues(0) : setSelectedIssues(issuesCnt); }; - console.log(`selectedIssues: ${selectedIssues}, isAnyissueSelected: ${isAnyIssueSelected}`); + console.log( + `selectedIssues: ${selectedIssues}, isAnyissueSelected: ${isAnyIssueSelected}` + ); useEffect(() => { if (selectedIssues === 0) setIsAnyIssueSelected(false); @@ -73,19 +95,33 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel {isAnyIssueSelected ? ( - theme.buttonWidths.lg} border={"none"}> - {isFilterClicked && } + theme.buttonWidths.lg} + border={"none"} + > + {isFilterClicked && } ) : ( {buttonNames.map((filter, idx) => ( - theme.buttonWidths.small} border={"none"} id={filter}> + theme.buttonWidths.small} + border={"none"} + id={filter} + > ))} - {isFilterClicked && } + {isFilterClicked && } {/* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state props로 내림 */} {/* 🔥recoil로 수정 필요 */} {/* 🔥회살표 클릭해도 필터 제대로 뜨도록 수정필요 */} @@ -127,7 +163,7 @@ const OpenCloseEdit = styled.div` const FiltersWrapper = styled.div` display: flex; justify-content: space-around; - /* position: relative; */ + position: relative; /* outline: red 1px solid; */ `; @@ -137,5 +173,5 @@ export const CheckBox = styled.div` `; const TextIconDivider = styled.div` - position: relative; + /* position: relative; */ `; diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index a9b521185..7baa7b261 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -4,15 +4,16 @@ import DropDownButton from "components/common/DropDownButton"; import theme from "styles/theme"; import FilterModal from "components/common/FilterModal"; import { useState, useEffect, useCallback } from "react"; -import { filter } from "data"; +import { clickedFilterAtomState } from "RecoilStore/Atoms"; +import { useSetRecoilState } from "recoil"; const MenuFilterBar = () => { const [isFilterClicked, setIsFilterClicked] = useState(false); - const [clickedFilter, setClickedFilter] = useState(""); + const setClickedFilterState = useSetRecoilState(clickedFilterAtomState); const handleClick = useCallback(e => { isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); - setClickedFilter(e.target.textContent); + setClickedFilterState(e.target.textContent); }); useEffect(() => { @@ -44,7 +45,7 @@ const MenuFilterBar = () => { - {isFilterClicked && } + {isFilterClicked && } ); }; diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index 30fa7f483..a45c9ed92 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -6,22 +6,24 @@ import FormLabel from "@material-ui/core/FormLabel"; import { useState } from "react"; import styled from "styled-components"; import { filter } from "data"; - +import { clickedFilterAtomState } from "RecoilStore/Atoms"; +import { useRecoilValue } from "recoil"; { /* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state내림 */ } -const FilterModal = ({ filterType }) => { +const FilterModal = () => { const [value, setValue] = useState(""); - console.log("filter modal"); + const filterType = useRecoilValue(clickedFilterAtomState); + // Recoil로직 (구현 예정) // 1. 필터별로 선택된 필터는 atom으로 관리됨(default는 null임) // 2. 이슈리스트 필터링, 검색창에 현재 선택된 필터들 보여줄 때는 그 Atom의 조합으로 보여줌 (특히 검색창엔 selector이용해서 붙이면 간단할듯) - const handleChange = (event) => { + const handleChange = event => { setValue(event.target.value); }; - const getFilterModalData = (type) => { + const getFilterModalData = type => { switch (type) { case "담당자": { return filter.assignee; @@ -47,12 +49,29 @@ const FilterModal = ({ filterType }) => { } }; const filterData = getFilterModalData(filterType); + return ( - {filterType === "필터" && ""} 필터 - - {filterData && filterData.map((x, idx) => } label={x} labelPlacement="start" key={idx} />)} + + {filterType === "필터" ? "" : filterType} 필터 + + + {filterData && + filterData.map((x, idx) => ( + } + label={x} + labelPlacement="start" + key={idx} + /> + ))} From bf837a73ef9d5b9f3fed07322b382bff9b743ae1 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Tue, 15 Jun 2021 16:45:07 +0900 Subject: [PATCH 16/71] =?UTF-8?q?fix:=20OAuth=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/pages/LoginLoadingPage.jsx | 11 ++++++----- frontend/src/components/pages/MainPage.jsx | 5 ++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/pages/LoginLoadingPage.jsx b/frontend/src/components/pages/LoginLoadingPage.jsx index 8afdd6244..2911d2c8c 100644 --- a/frontend/src/components/pages/LoginLoadingPage.jsx +++ b/frontend/src/components/pages/LoginLoadingPage.jsx @@ -7,18 +7,19 @@ const LoginLoadingPage = () => { const getToken = async () => { const params = new URLSearchParams(window.location.search); const code = params.get("code"); - console.log(code); const res = await fetch(API.login(code)); const json = await res.json(); const { accessToken, tokenType } = json; - localStorage.setItem("accessToken", accessToken); - localStorage.setItem("tokeType", tokenType); - setIsLogin(true); + accessToken && localStorage.setItem("accessToken", accessToken); + tokenType && localStorage.setItem("tokeType", tokenType); + if (res.ok) setIsLogin(true); + if (!res.ok) setIsLogin(false); }; useEffect(() => { getToken(); }, []); - return <>${isLogin ? :
로딩
}; + + return <>{isLogin ? : <>Loading..}; }; export default LoginLoadingPage; diff --git a/frontend/src/components/pages/MainPage.jsx b/frontend/src/components/pages/MainPage.jsx index 38f3fe475..909793b5c 100644 --- a/frontend/src/components/pages/MainPage.jsx +++ b/frontend/src/components/pages/MainPage.jsx @@ -29,11 +29,10 @@ const MainPage = () => { ) : ( - + ); }; -const MainPageLayout = styled.div` -`; +const MainPageLayout = styled.div``; export default MainPage; From e639d34c106486f908951b70cf5e62746b1169ab Mon Sep 17 00:00:00 2001 From: junzero741 Date: Tue, 15 Jun 2021 18:23:53 +0900 Subject: [PATCH 17/71] =?UTF-8?q?feat:=20=EC=9C=A0=EC=A0=80=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/common/Header.jsx | 20 ++++++++++++++++++-- frontend/src/util/getUserInfo.js | 8 ++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 frontend/src/util/getUserInfo.js diff --git a/frontend/src/components/common/Header.jsx b/frontend/src/components/common/Header.jsx index 128664f79..9e9147573 100644 --- a/frontend/src/components/common/Header.jsx +++ b/frontend/src/components/common/Header.jsx @@ -1,15 +1,19 @@ import styled from "styled-components"; import { ReactComponent as Logo } from "images/LogotypeMedium.svg"; -import { ReactComponent as UserImg } from "images/UserImageLarge.svg"; import { Link } from "react-router-dom"; +import getUserInfo from "util/getUserInfo"; const Header = () => { + const userInfo = getUserInfo(); + console.log(userInfo); return ( - + + {userInfo.gitHubId} + ); }; @@ -21,3 +25,15 @@ const StyleHeader = styled.div` justify-content: space-between; width: 100%; `; + +const ImgWrapper = styled.div` + width: 44px; + height: 44px; + border: 1px solid ${({ theme }) => theme.grayScale.line}; + border-radius: 50%; + overflow: hidden; + img { + width: 100%; + height: 100%; + } +`; diff --git a/frontend/src/util/getUserInfo.js b/frontend/src/util/getUserInfo.js new file mode 100644 index 000000000..b1feedbae --- /dev/null +++ b/frontend/src/util/getUserInfo.js @@ -0,0 +1,8 @@ +const getUserInfo = () => { + const token = localStorage.getItem("accessToken"); + const parsedToken = atob(token.split(".")[1]); + const { imageUrl, gitHubId, iss, id, exp } = JSON.parse(parsedToken); + return { imageUrl, gitHubId, iss, id, exp }; +}; + +export default getUserInfo; From 96edb8ddd091eb60d5ecde5b6bbaf9c79d2260a2 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Wed, 16 Jun 2021 00:38:48 +0900 Subject: [PATCH 18/71] =?UTF-8?q?refactor:=20=EC=B2=B4=ED=81=AC=ED=95=9C?= =?UTF-8?q?=20=EC=9D=B4=EC=8A=88=20Set=EC=9C=BC=EB=A1=9C=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Issues/IssueList/IssueCard.jsx | 37 +++++++++++-- .../components/Issues/IssueList/IssueList.jsx | 31 +++++++++-- .../Issues/IssueList/IssuesHeader.jsx | 55 +++++++++++++++---- 3 files changed, 100 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index a69f7e95c..e86e940f3 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -11,21 +11,45 @@ import getTimeStamp from "util/getTimeStamp"; import { selectedIssueCntAtomState } from "RecoilStore/Atoms"; import { useRecoilState } from "recoil"; -const IssueCard = ({ issue, setIsAnyIssueSelected, isAllIssueSelected, setIsAllIssueSelected, initCheck, setInitCheck, selectedCards, setSelectedCards }) => { +const IssueCard = ({ + issue, + setIsAnyIssueSelected, + isAllIssueSelected, + setIsAllIssueSelected, + selectedCards, + setSelectedCards, +}) => { const [isChecked, setIsChecked] = useState(false); - const [selectedIssues, setSelectedIssues] = useRecoilState(selectedIssueCntAtomState); + const [selectedIssues, setSelectedIssues] = useRecoilState( + selectedIssueCntAtomState + ); const { title, id, labelId, milestoneId, author, createdAt } = issue; const handleCheck = () => { setIsChecked(!isChecked); - isChecked ? setSelectedIssues(selectedIssues - 1) : setSelectedIssues(selectedIssues + 1); + if (isChecked) { + setSelectedIssues(selectedIssues - 1); + selectedCards.delete(id); + } + if (!isChecked) { + setSelectedIssues(selectedIssues + 1); + setSelectedCards(selectedCards.add(id)); + } }; - + console.log(selectedCards); + // console.log(selectedIssues); useEffect(() => { isChecked ? setIsAnyIssueSelected(true) : setIsAnyIssueSelected(false); }, [isChecked]); useEffect(() => { - isAllIssueSelected ? setIsChecked(true) : setIsChecked(false); + if (isAllIssueSelected) { + setIsChecked(true); + setSelectedCards(selectedCards.add(id)); + } + if (!isAllIssueSelected) { + setIsChecked(false); + selectedCards.delete(id); + } }, [isAllIssueSelected]); return ( @@ -47,7 +71,8 @@ const IssueCard = ({ issue, setIsAnyIssueSelected, isAllIssueSelected, setIsAllI #{id} - 이 이슈가 {getTimeStamp(createdAt)}, {author}님에 의해 작성되었습니다 + 이 이슈가 {getTimeStamp(createdAt)}, {author}님에 의해 + 작성되었습니다 diff --git a/frontend/src/components/Issues/IssueList/IssueList.jsx b/frontend/src/components/Issues/IssueList/IssueList.jsx index b33492bef..09229940b 100644 --- a/frontend/src/components/Issues/IssueList/IssueList.jsx +++ b/frontend/src/components/Issues/IssueList/IssueList.jsx @@ -11,20 +11,41 @@ import { selectedIssueCntAtomState } from "RecoilStore/Atoms"; const IssueList = () => { const [isAnyIssueSelected, setIsAnyIssueSelected] = useState(false); // 상태 위치 협의 후 수정 const [isAllIssueSelected, setIsAllIssueSelected] = useState(false); - const [initCheck, setInitCheck] = useState(true); const [_, setSelectedIssues] = useRecoilState(selectedIssueCntAtomState); const [selectedCards, setSelectedCards] = useState(new Set()); useEffect(() => { - if (!initCheck && !isAllIssueSelected && !isAnyIssueSelected) setSelectedIssues(() => 0); + if (!isAllIssueSelected && !isAnyIssueSelected && !selectedCards.size) + setSelectedIssues(() => 0); }, [isAnyIssueSelected]); - const issueList = issues.map((issue) => ); + const issueList = issues.map(issue => ( + + )); return ( - - {issueList.length ? issueList : 검색과 일치하는 결과가 없습니다} + + {issueList.length ? ( + issueList + ) : ( + 검색과 일치하는 결과가 없습니다 + )} ); }; diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index 7c69f1e97..f6c8cbf67 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -11,17 +11,31 @@ import { filter } from "data"; // import { selectedIssueCntAtomState, clickedFilterAtomState } from "MyRecoil/atom"; // import { useRecoilState } from "MyRecoil"; import { useRecoilState } from "recoil"; -import { selectedIssueCntAtomState, clickedFilterAtomState } from "RecoilStore/Atoms"; - -const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSelected, setIsAllIssueSelected, issuesCnt, initCheck, setInitCheck }) => { - const [selectedIssues, setSelectedIssues] = useRecoilState(selectedIssueCntAtomState); +import { + selectedIssueCntAtomState, + clickedFilterAtomState, +} from "RecoilStore/Atoms"; + +const IssuesHeader = ({ + isAnyIssueSelected, + setIsAnyIssueSelected, + isAllIssueSelected, + setIsAllIssueSelected, + issuesCnt, + selectedCards, +}) => { + const [selectedIssues, setSelectedIssues] = useRecoilState( + selectedIssueCntAtomState + ); const buttonNames = ["담당자", "레이블", "마일스톤", "작성자"]; const [clickedFilter, setClickedFilter] = useState(""); //----------중복 코드from MeuFilter -------- const [isFilterClicked, setIsFilterClicked] = useState(false); - const handleClick = useCallback((e) => { - isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); + const handleClick = useCallback(e => { + isFilterClicked === false + ? setIsFilterClicked(true) + : setIsFilterClicked(false); console.dir(e.target.textContent); console.dir(e.target); setClickedFilter(e.target.textContent); @@ -34,9 +48,14 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel }; }, [isFilterClicked]); - const closeFilterModal = (e) => { + const closeFilterModal = e => { const target = e.target; - if (isFilterClicked && !target.closest(".filter-modal") && !target.closest(".issue-header-button")) setIsFilterClicked(false); + if ( + isFilterClicked && + !target.closest(".filter-modal") && + !target.closest(".issue-header-button") + ) + setIsFilterClicked(false); }; //----------여기 까지 중복 코드from MeuFilter --------/ @@ -45,8 +64,6 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel isAllIssueSelected ? setSelectedIssues(0) : setSelectedIssues(issuesCnt); }; - console.log(`selectedIssues: ${selectedIssues}, isAnyissueSelected: ${isAnyIssueSelected}`); - useEffect(() => { if (selectedIssues === 0) setIsAnyIssueSelected(false); else setIsAnyIssueSelected(true); @@ -73,7 +90,13 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel {isAnyIssueSelected ? ( - theme.buttonWidths.lg} border={"none"}> + theme.buttonWidths.lg} + border={"none"} + > {isFilterClicked && } @@ -81,7 +104,15 @@ const IssuesHeader = ({ isAnyIssueSelected, setIsAnyIssueSelected, isAllIssueSel {buttonNames.map((filter, idx) => ( - theme.buttonWidths.small} border={"none"} id={filter}> + theme.buttonWidths.small} + border={"none"} + id={filter} + > ))} From aaf9c08ed81623ce2cae19c730b7bd8c0cfabe31 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Wed, 16 Jun 2021 01:04:38 +0900 Subject: [PATCH 19/71] =?UTF-8?q?feat:=20=EB=A9=94=EC=9D=B8=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=ED=83=AD=20=EB=B2=84=ED=8A=BC=20=ED=81=B4=EB=A6=AD?= =?UTF-8?q?=EB=B3=84=EB=A1=9C=20=EB=9D=BC=EC=9A=B0=ED=8C=85=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.jsx | 2 +- .../src/components/Issues/Menu/MenuTab.jsx | 5 ++- .../src/components/common/ButtonGroup.jsx | 37 +++++++++++-------- frontend/src/components/pages/LabelsPage.jsx | 2 +- .../src/components/pages/MilestonesPage.jsx | 2 +- .../src/components/pages/NewIssuePage.jsx | 2 +- 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 5e981514b..f14a088be 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -26,7 +26,7 @@ function App() { - {/* */} + diff --git a/frontend/src/components/Issues/Menu/MenuTab.jsx b/frontend/src/components/Issues/Menu/MenuTab.jsx index 22bc825bb..87e80b21b 100644 --- a/frontend/src/components/Issues/Menu/MenuTab.jsx +++ b/frontend/src/components/Issues/Menu/MenuTab.jsx @@ -1,10 +1,13 @@ import ButtonGroup from "components/common/ButtonGroup"; import AddButton from "components/common/AddButton"; +import { Link } from "react-router-dom"; const MenuTab = () => { return (
- + + +
); }; diff --git a/frontend/src/components/common/ButtonGroup.jsx b/frontend/src/components/common/ButtonGroup.jsx index 157ecc583..3fdb2b656 100644 --- a/frontend/src/components/common/ButtonGroup.jsx +++ b/frontend/src/components/common/ButtonGroup.jsx @@ -7,6 +7,7 @@ import styled from "styled-components"; import { ReactComponent as LabelIcon } from "images/tag.svg"; import { ReactComponent as MileStoneIcon } from "images/milestone.svg"; import theme from "styles/theme"; +import { Link } from "react-router-dom"; const ButtonGroup = ({ milestoneCount, @@ -17,22 +18,26 @@ const ButtonGroup = ({ }) => { return ( <> - theme.buttonWidths.base} - _radius={"left"} - > - - 마일스톤 ({milestoneCount}) - - theme.buttonWidths.base} - _radius={"right"} - > - - 레이블 ({labelCount}) - + + theme.buttonWidths.base} + _radius={"left"} + > + + 마일스톤 ({milestoneCount}) + + + + theme.buttonWidths.base} + _radius={"right"} + > + + 레이블 ({labelCount}) + + ); }; diff --git a/frontend/src/components/pages/LabelsPage.jsx b/frontend/src/components/pages/LabelsPage.jsx index 3f1c40b1f..61ed9bd07 100644 --- a/frontend/src/components/pages/LabelsPage.jsx +++ b/frontend/src/components/pages/LabelsPage.jsx @@ -1,5 +1,5 @@ const LabelsPage = () => { - return
; + return
라벨페이지
; }; export default LabelsPage; diff --git a/frontend/src/components/pages/MilestonesPage.jsx b/frontend/src/components/pages/MilestonesPage.jsx index 9b367f208..e5aab1987 100644 --- a/frontend/src/components/pages/MilestonesPage.jsx +++ b/frontend/src/components/pages/MilestonesPage.jsx @@ -1,5 +1,5 @@ const MilestonesPage = () => { - return
; + return
마일스톤페이지
; }; export default MilestonesPage; diff --git a/frontend/src/components/pages/NewIssuePage.jsx b/frontend/src/components/pages/NewIssuePage.jsx index fe36492fe..8bdf5c530 100644 --- a/frontend/src/components/pages/NewIssuePage.jsx +++ b/frontend/src/components/pages/NewIssuePage.jsx @@ -1,5 +1,5 @@ function NewIssue() { - return
새로운 이슈 글
; + return
새로운 이슈 쓰기 페이지
; } export default NewIssue; From 049c6fd4fc4610e6eff652e7b000e30b8df90c14 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Wed, 16 Jun 2021 14:11:43 +0900 Subject: [PATCH 20/71] =?UTF-8?q?WIP:=20filterbar=20input=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EC=A4=91(#29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 83 ++++++++++++++++++- .../Issues/IssueList/IssuesHeader.jsx | 3 + .../components/Issues/Menu/MenuFilterBar.jsx | 14 +++- .../src/components/common/FilterModal.jsx | 14 +++- frontend/src/util/API.js | 15 ++++ 5 files changed, 121 insertions(+), 8 deletions(-) diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 7bfba9033..2cc505b0b 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -1,4 +1,4 @@ -import { atom } from "recoil"; +import { atom, selector } from "recoil"; export const selectedIssueCntAtomState = atom({ key: "selectedIssueCntAtomState", @@ -9,3 +9,84 @@ export const clickedFilterAtomState = atom({ key: "clickedFilterAtomState", default: null, }); + +export const assigneeFilterAtomState = atom({ + key: "assigneeFilterAtomState", + default: null, +}); + +export const labelFilterAtomState = atom({ + key: "labelFilterAtomState", + default: null, +}); + +export const milestoneFilterAtomState = atom({ + key: "milestoneFilterAtomState", + default: null, +}); + +export const authorFilterAtomState = atom({ + key: "authorFilterAtomState", + default: null, +}); + +export const issueFilterAtomState = atom({ + key: "issueFilterAtomState", + default: null, +}); + +export const filterBarInputAtomState = atom({ + key: "filterBarInputAtomState", + default: { + placeholder: "is:issue is:open", + assignee: null, + label: null, + milestone: null, + author: null, + issue: null, + }, +}); +// export const filterBarInputAtomState = selector({ +// key: "filterBarInputAtomState", +// get: ({ get }) => { +// const placeholder = "is:issue is:open"; +// const assignee = get(assigneeFilterAtomState); +// const label = get(labelFilterAtomState); +// const milestone = get(milestoneFilterAtomState); +// const author = get(authorFilterAtomState); +// const issue = get(issueFilterAtomState); +// const filters = [placeholder, assignee, label, milestone, author, issue]; +// console.log("assignee", assignee); +// console.log(filters); +// return filters.reduce((acc, item) => { +// if (item) acc += item; +// return acc; +// }, ""); +// }, +// set: ({ set }, filterType) => { +// switch (filterType) { +// case "담당자": { +// set(assigneeFilterAtomState, clickedFilterAtomState); +// break; +// } +// case "레이블": { +// set(labelFilterAtomState, clickedFilterAtomState); +// break; +// } +// case "마일스톤": { +// set(milestoneFilterAtomState, clickedFilterAtomState); +// break; +// } +// case "작성자": { +// set(authorFilterAtomState, clickedFilterAtomState); +// break; +// } +// case "필터": { +// set(issueFilterAtomState, clickedFilterAtomState); +// break; +// } +// default: +// throw new Error("Unhandled Type"); +// } +// }, +// }); diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index 15ee7e95d..589ef5d5a 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -14,6 +14,7 @@ import { useRecoilState, useSetRecoilState } from "recoil"; import { selectedIssueCntAtomState, clickedFilterAtomState, + filterBarInputAtomState, } from "RecoilStore/Atoms"; const IssuesHeader = ({ @@ -30,6 +31,7 @@ const IssuesHeader = ({ ); const buttonNames = ["담당자", "레이블", "마일스톤", "작성자"]; const setClickedFilterState = useSetRecoilState(clickedFilterAtomState); + const setFilterBarInputState = useSetRecoilState(filterBarInputAtomState); //----------중복 코드from MeuFilter -------- const [isFilterClicked, setIsFilterClicked] = useState(false); @@ -40,6 +42,7 @@ const IssuesHeader = ({ console.dir(e.target.textContent); console.dir(e.target); setClickedFilterState(e.target.textContent); + setFilterBarInputState(e.target.textContent); //여기 }); useEffect(() => { diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index 7baa7b261..9f8116172 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -4,11 +4,17 @@ import DropDownButton from "components/common/DropDownButton"; import theme from "styles/theme"; import FilterModal from "components/common/FilterModal"; import { useState, useEffect, useCallback } from "react"; -import { clickedFilterAtomState } from "RecoilStore/Atoms"; -import { useSetRecoilState } from "recoil"; +import { + clickedFilterAtomState, + filterBarInputAtomState, +} from "RecoilStore/Atoms"; +import { useSetRecoilState, useRecoilValue } from "recoil"; const MenuFilterBar = () => { const [isFilterClicked, setIsFilterClicked] = useState(false); const setClickedFilterState = useSetRecoilState(clickedFilterAtomState); + const filterBarInput = useRecoilValue(filterBarInputAtomState); + console.log(filterBarInput); + const handleClick = useCallback(e => { isFilterClicked === false ? setIsFilterClicked(true) @@ -39,9 +45,9 @@ const MenuFilterBar = () => { radius={"left"} /> - + - is:issue is:open + diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index a45c9ed92..2d503752d 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -6,21 +6,29 @@ import FormLabel from "@material-ui/core/FormLabel"; import { useState } from "react"; import styled from "styled-components"; import { filter } from "data"; -import { clickedFilterAtomState } from "RecoilStore/Atoms"; -import { useRecoilValue } from "recoil"; +import { + filterBarInputAtomState, + clickedFilterAtomState, +} from "RecoilStore/Atoms"; +import { useRecoilValue, useSetRecoilState } from "recoil"; { /* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state내림 */ } const FilterModal = () => { const [value, setValue] = useState(""); const filterType = useRecoilValue(clickedFilterAtomState); + const setFilterBarInputState = useSetRecoilState(filterBarInputAtomState); // Recoil로직 (구현 예정) // 1. 필터별로 선택된 필터는 atom으로 관리됨(default는 null임) - // 2. 이슈리스트 필터링, 검색창에 현재 선택된 필터들 보여줄 때는 그 Atom의 조합으로 보여줌 (특히 검색창엔 selector이용해서 붙이면 간단할듯) + // 2. 이슈리스트 필터링, 검색창에 현재 선택된 ent.target.value); + //필터들 보여줄 때는 그 Atom의 조합으로 보여줌 (특히 검색창엔 selector이용해서 붙이면 간단할듯) + // const handleChange = event => { setValue(event.target.value); + console.log(event.target.value); + setFilterBarInputState(filterType); }; const getFilterModalData = type => { diff --git a/frontend/src/util/API.js b/frontend/src/util/API.js index 19d143b5d..f324b0000 100644 --- a/frontend/src/util/API.js +++ b/frontend/src/util/API.js @@ -8,5 +8,20 @@ const API = { gitHubOAuth() { return "https://github.com/login/oauth/authorize?client_id=c39689919134be7915cf&redirect_uri=http://localhost:3000/login"; }, + labels() { + return `${this.default()}/labels`; + }, + labelsId(id) { + return `${this.default()}/labels/${id}`; + }, + milestones() { + return `${this.default()}/milestones`; + }, + milestonesId(id) { + return `${this.default()}/milestones/${id}`; + }, + users() { + return `${this.default()}/users`; + }, }; export default API; From 12f1c2f979e9aea51b002a14d69918469140ddfb Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Wed, 16 Jun 2021 16:11:00 +0900 Subject: [PATCH 21/71] =?UTF-8?q?WIP:=20menu=20filter=20bar=20share=20?= =?UTF-8?q?=EC=9A=A9=20commit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Issues/IssueList/IssuesHeader.jsx | 6 +- .../src/components/common/FilterModal.jsx | 61 +++++++++++++++++-- frontend/src/data.js | 8 ++- frontend/src/util/getUserInfo.js | 8 ++- 4 files changed, 70 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index cf5a158bc..38ca9db02 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -24,14 +24,13 @@ const IssuesHeader = ({ setIsAllIssueSelected, issuesCnt, selectedCards, - }) => { const [selectedIssues, setSelectedIssues] = useRecoilState( selectedIssueCntAtomState ); const buttonNames = ["담당자", "레이블", "마일스톤", "작성자"]; const setClickedFilterState = useSetRecoilState(clickedFilterAtomState); - const setFilterBarInputState = useSetRecoilState(filterBarInputAtomState); + // const setFilterBarInputState = useSetRecoilState(filterBarInputAtomState); //----------중복 코드from MeuFilter -------- const [isFilterClicked, setIsFilterClicked] = useState(false); @@ -42,7 +41,7 @@ const IssuesHeader = ({ console.dir(e.target.textContent); console.dir(e.target); setClickedFilterState(e.target.textContent); - setFilterBarInputState(e.target.textContent); //여기 + // setFilterBarInputState(e.target.textContent); //여기 }); useEffect(() => { @@ -68,7 +67,6 @@ const IssuesHeader = ({ isAllIssueSelected ? setSelectedIssues(0) : setSelectedIssues(issuesCnt); }; - useEffect(() => { if (selectedIssues === 0) setIsAnyIssueSelected(false); else setIsAnyIssueSelected(true); diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index 2d503752d..7882c8c59 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -10,14 +10,16 @@ import { filterBarInputAtomState, clickedFilterAtomState, } from "RecoilStore/Atoms"; -import { useRecoilValue, useSetRecoilState } from "recoil"; +import { useRecoilValue, useSetRecoilState, useRecoilState } from "recoil"; { /* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state내림 */ } const FilterModal = () => { const [value, setValue] = useState(""); const filterType = useRecoilValue(clickedFilterAtomState); - const setFilterBarInputState = useSetRecoilState(filterBarInputAtomState); + const [filterBarInputState, setFilterBarInputState] = useRecoilState( + filterBarInputAtomState + ); // Recoil로직 (구현 예정) // 1. 필터별로 선택된 필터는 atom으로 관리됨(default는 null임) @@ -27,8 +29,54 @@ const FilterModal = () => { // const handleChange = event => { setValue(event.target.value); + console.log(filterType); console.log(event.target.value); - setFilterBarInputState(filterType); + setFilterStateByType(value); + }; + const setFilterStateByType = selectedFilter => { + console.log(filterType); + switch (filterType) { + case "담당자": { + console.log("담당자,filterBarInputState"); + setFilterBarInputState({ + ...filterBarInputState, + assignee: selectedFilter, + }); + break; + } + case "레이블": { + setFilterBarInputState({ + ...filterBarInputState, + label: selectedFilter, + }); + break; + } + case "마일스톤": { + setFilterBarInputState({ + ...filterBarInputState, + milestone: selectedFilter, + }); + break; + } + case "작성자": { + setFilterBarInputState({ + ...filterBarInputState, + author: selectedFilter, + }); + break; + } + case "필터": { + setFilterBarInputState({ + ...filterBarInputState, + issue: selectedFilter, + }); + break; + } + default: { + console.error("setFilterStateByType unhandled type"); + } + } + console.log(filterBarInputState); }; const getFilterModalData = type => { @@ -71,11 +119,11 @@ const FilterModal = () => { onChange={handleChange} > {filterData && - filterData.map((x, idx) => ( + filterData.map((filter, idx) => ( } - label={x} + label={filter} labelPlacement="start" key={idx} /> @@ -98,6 +146,7 @@ const FilterControlLabel = styled(FormControlLabel)` display: flex; justify-content: space-between; margin: 0; + outline: 1px solid red; `; const FilterRadioContainer = styled(RadioGroup)` diff --git a/frontend/src/data.js b/frontend/src/data.js index 439bed72b..b1baf6a04 100644 --- a/frontend/src/data.js +++ b/frontend/src/data.js @@ -20,7 +20,13 @@ export const issues = [ ]; export const filter = { - issue: ["열린 이슈", "내가 작성한 이슈", "나에게 할당한 이슈", "나에게 할당된 이슈", "내가 댓글을 남긴 이슈", "닫힌 이슈"], + issue: [ + "열린 이슈", + "내가 작성한 이슈", + "나에게 할당된 이슈", + "내가 댓글을 남긴 이슈", + "닫힌 이슈", + ], assignee: ["daisy", "goody"], label: ["bug", "document"], milestone: ["마일스톤이 없는 필터", "마스터즈 코스"], diff --git a/frontend/src/util/getUserInfo.js b/frontend/src/util/getUserInfo.js index b1feedbae..311954a84 100644 --- a/frontend/src/util/getUserInfo.js +++ b/frontend/src/util/getUserInfo.js @@ -1,8 +1,12 @@ const getUserInfo = () => { const token = localStorage.getItem("accessToken"); + console.log(token.split(".")[1]); const parsedToken = atob(token.split(".")[1]); - const { imageUrl, gitHubId, iss, id, exp } = JSON.parse(parsedToken); - return { imageUrl, gitHubId, iss, id, exp }; + const { nickName, imageUrl, gitHubId, iss, id, exp } = JSON.parse( + parsedToken + ); + console.log(nickName, imageUrl, gitHubId, iss, id, exp); + return { nickName, imageUrl, gitHubId, iss, id, exp }; }; export default getUserInfo; From 9c75e9d4c75e9cbba3d332b1bb586c3110c138e1 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Wed, 16 Jun 2021 17:27:36 +0900 Subject: [PATCH 22/71] =?UTF-8?q?feat:=20=ED=95=84=ED=84=B0=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=20=EB=9D=BC=EB=94=94=EC=98=A4=20=EB=A7=88=EC=A7=80?= =?UTF-8?q?=EB=A7=89=20=ED=81=B4=EB=A6=AD=20=EA=B8=B0=EC=96=B5=20(#29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 7 ++- .../src/components/common/FilterModal.jsx | 59 +++++++------------ frontend/src/util/getEngKey.js | 18 ++++++ 3 files changed, 43 insertions(+), 41 deletions(-) create mode 100644 frontend/src/util/getEngKey.js diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 2cc505b0b..1bc6419df 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -39,13 +39,14 @@ export const filterBarInputAtomState = atom({ key: "filterBarInputAtomState", default: { placeholder: "is:issue is:open", - assignee: null, - label: null, - milestone: null, + assignee: null, // asignee 필터 모달 에서 마지막으로 클릭한 값이 저장 + label: null, // label 필터모달 에서 마지막으로 클릭한 값이 저장 + milestone: null, // "마일스톤": null author: null, issue: null, }, }); + // export const filterBarInputAtomState = selector({ // key: "filterBarInputAtomState", // get: ({ get }) => { diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index 7882c8c59..4e03e4059 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -1,3 +1,4 @@ +import { useEffect } from "react"; import Radio from "@material-ui/core/Radio"; import RadioGroup from "@material-ui/core/RadioGroup"; import FormControlLabel from "@material-ui/core/FormControlLabel"; @@ -11,6 +12,7 @@ import { clickedFilterAtomState, } from "RecoilStore/Atoms"; import { useRecoilValue, useSetRecoilState, useRecoilState } from "recoil"; +import getEngKey from "util/getEngKey"; { /* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state내림 */ } @@ -27,48 +29,50 @@ const FilterModal = () => { //필터들 보여줄 때는 그 Atom의 조합으로 보여줌 (특히 검색창엔 selector이용해서 붙이면 간단할듯) // + const handleChange = event => { setValue(event.target.value); - console.log(filterType); - console.log(event.target.value); - setFilterStateByType(value); + setFilterStateByType(event.target.value); }; - const setFilterStateByType = selectedFilter => { - console.log(filterType); + + const key = getEngKey(filterType); + + const setFilterStateByType = value => { + // console.log(filterType); switch (filterType) { case "담당자": { console.log("담당자,filterBarInputState"); setFilterBarInputState({ ...filterBarInputState, - assignee: selectedFilter, + assignee: value, }); break; } case "레이블": { setFilterBarInputState({ ...filterBarInputState, - label: selectedFilter, + label: value, }); break; } case "마일스톤": { setFilterBarInputState({ ...filterBarInputState, - milestone: selectedFilter, + milestone: value, }); break; } case "작성자": { setFilterBarInputState({ ...filterBarInputState, - author: selectedFilter, + author: value, }); break; } case "필터": { setFilterBarInputState({ ...filterBarInputState, - issue: selectedFilter, + issue: value, }); break; } @@ -76,36 +80,14 @@ const FilterModal = () => { console.error("setFilterStateByType unhandled type"); } } - console.log(filterBarInputState); }; const getFilterModalData = type => { - switch (type) { - case "담당자": { - return filter.assignee; - } - case "레이블": { - return filter.label; - } - case "마일스톤": { - return filter.milestone; - } - case "작성자": { - return filter.author; - } - case "필터": { - return filter.issue; - } - case "상태 수정": { - return filter.openClose; - } - default: { - console.error("unhandled type"); - } - } + return filter[getEngKey(type)]; }; - const filterData = getFilterModalData(filterType); + const filterData = getFilterModalData(filterType); + console.log(filterData); return ( @@ -119,13 +101,14 @@ const FilterModal = () => { onChange={handleChange} > {filterData && - filterData.map((filter, idx) => ( + filterData.map((text, idx) => ( } - label={filter} + label={text} labelPlacement="start" key={idx} + checked={filterBarInputState[key] === text} // /> ))} diff --git a/frontend/src/util/getEngKey.js b/frontend/src/util/getEngKey.js new file mode 100644 index 000000000..c3723825f --- /dev/null +++ b/frontend/src/util/getEngKey.js @@ -0,0 +1,18 @@ +const getEngKey = str => { + switch (str) { + case "담당자": + return "assignee"; + case "레이블": + return "label"; + case "마일스톤": + return "milestone"; + case "작성자": + return "author"; + case "필터": + return "issue"; + default: + console.error("unhandled English name"); + } +}; + +export default getEngKey; From b715caa6d5c62996588349df85b01766587458b4 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Wed, 16 Jun 2021 21:19:32 +0900 Subject: [PATCH 23/71] =?UTF-8?q?feat:=20=EC=84=A0=ED=83=9D=ED=95=9C=20fil?= =?UTF-8?q?ter=20filterBarInput=EC=97=90=20=EB=B3=B4=EC=97=AC=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=99=84=EC=84=B1(#29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Issues/Menu/MenuFilterBar.jsx | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index 9f8116172..50bd92290 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -13,7 +13,17 @@ const MenuFilterBar = () => { const [isFilterClicked, setIsFilterClicked] = useState(false); const setClickedFilterState = useSetRecoilState(clickedFilterAtomState); const filterBarInput = useRecoilValue(filterBarInputAtomState); - console.log(filterBarInput); + + const getFilterBarString = () => { + return Object.entries(filterBarInput).reduce((acc, item) => { + if (item[1]) { + if (item[0] === "placeholder") acc += `${item[1]} `; + else acc += `${item[0]}:${item[1]} `; + } + console.log(acc); + return acc; + }, ""); + }; const handleClick = useCallback(e => { isFilterClicked === false @@ -45,9 +55,13 @@ const MenuFilterBar = () => { radius={"left"} /> - - - + + + + + @@ -58,9 +72,10 @@ const MenuFilterBar = () => { const MenuFilterLayout = styled.div` display: flex; - width: 601px; + width: 700px; height: 40px; position: relative; + margin-bottom: 24px; `; const FilterInputContainer = styled.div` width: 100%; @@ -72,13 +87,20 @@ const FilterInput = styled.div` display: flex; width: 100%; height: 100%; - padding: 2.3%; + padding: 0; background-color: ${theme.grayScale.input_background}; border-radius: ${theme.border_radius_mix.right}; `; -const FilterInputText = styled.div` - padding: 0.4% 2%; +const FilterInputIconContainer = styled.div` + padding: 11px; +`; +const FilterInputText = styled.input` + width: 100%; + height: 100%; + border: none; + background-color: ${theme.grayScale.input_background}; color: ${theme.grayScale.placeholder}; + border-radius: ${theme.border_radius_mix.right}; `; export default MenuFilterBar; From a8dfa0e6bfe7f637bfe65e982568c880b5058acc Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Wed, 16 Jun 2021 21:19:52 +0900 Subject: [PATCH 24/71] =?UTF-8?q?feat:=20padding=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/common/FilterModal.jsx | 3 +-- frontend/src/components/common/Header.jsx | 1 + frontend/src/components/pages/MainPage.jsx | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index 4e03e4059..ba8c16e4e 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -118,7 +118,7 @@ const FilterModal = () => { }; const FilterModalLayout = styled.div` position: absolute; - top: 110%; + top: 45px; background-color: white; text-align: left; border-radius: 16px; @@ -129,7 +129,6 @@ const FilterControlLabel = styled(FormControlLabel)` display: flex; justify-content: space-between; margin: 0; - outline: 1px solid red; `; const FilterRadioContainer = styled(RadioGroup)` diff --git a/frontend/src/components/common/Header.jsx b/frontend/src/components/common/Header.jsx index 9e9147573..c10495210 100644 --- a/frontend/src/components/common/Header.jsx +++ b/frontend/src/components/common/Header.jsx @@ -24,6 +24,7 @@ const StyleHeader = styled.div` display: flex; justify-content: space-between; width: 100%; + padding: 27px 0px; `; const ImgWrapper = styled.div` diff --git a/frontend/src/components/pages/MainPage.jsx b/frontend/src/components/pages/MainPage.jsx index 909793b5c..1a59fd4b2 100644 --- a/frontend/src/components/pages/MainPage.jsx +++ b/frontend/src/components/pages/MainPage.jsx @@ -33,6 +33,8 @@ const MainPage = () => { ); }; -const MainPageLayout = styled.div``; +const MainPageLayout = styled.div` + padding: 0 5%; +`; export default MainPage; From 0a79348ce7da3e0ef6efb1caefa0acff0a0deda2 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Wed, 16 Jun 2021 21:38:25 +0900 Subject: [PATCH 25/71] =?UTF-8?q?feat:=20=EC=83=88=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20HTML=20=ED=8B=80=20=EC=9E=A1=EA=B8=B0=20(#?= =?UTF-8?q?55)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/NewIssues/NewIssueForm.jsx | 34 +++++++++++++++++++ .../components/NewIssues/NewIssueInput.jsx | 13 +++++++ .../src/components/common/CancelButton.jsx | 11 ++++++ .../src/components/common/CommentInput.jsx | 5 +++ frontend/src/components/common/Header.jsx | 1 - .../components/common/IssueCategoryList.jsx | 5 +++ .../src/components/common/SubmitButton.jsx | 11 ++++++ .../src/components/pages/NewIssuePage.jsx | 16 ++++++++- frontend/src/styles/StyledButtons.jsx | 11 +++++- frontend/src/styles/theme.js | 2 +- frontend/src/util/getUserInfo.js | 7 ++-- 11 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 frontend/src/components/common/CancelButton.jsx create mode 100644 frontend/src/components/common/SubmitButton.jsx diff --git a/frontend/src/components/NewIssues/NewIssueForm.jsx b/frontend/src/components/NewIssues/NewIssueForm.jsx index e69de29bb..8240ae742 100644 --- a/frontend/src/components/NewIssues/NewIssueForm.jsx +++ b/frontend/src/components/NewIssues/NewIssueForm.jsx @@ -0,0 +1,34 @@ +import styled from "styled-components"; +import NewIssueInput from "./NewIssueInput"; +import IssueCategoryList from "components/common/IssueCategoryList"; +import SubmitButton from "components/common/SubmitButton"; +import CancelButton from "components/common/CancelButton"; + +const NewIssueForm = () => { + return ( + <> + + + + + + x 작성 취소 + 완료 + + + ); +}; + +export default NewIssueForm; + +const Wrapper = styled.div` + display: flex; + padding: ${({ theme }) => `${theme.fontSizes.titleSize} 0`}; + border-bottom: 1px solid ${({ theme }) => theme.grayScale.line}; +`; + +const ButtonWrapper = styled.div` + display: flex; + justify-content: flex-end; + padding: ${({ theme }) => `${theme.fontSizes.titleSize} 0`}; +`; diff --git a/frontend/src/components/NewIssues/NewIssueInput.jsx b/frontend/src/components/NewIssues/NewIssueInput.jsx index e69de29bb..91790d9c5 100644 --- a/frontend/src/components/NewIssues/NewIssueInput.jsx +++ b/frontend/src/components/NewIssues/NewIssueInput.jsx @@ -0,0 +1,13 @@ +import CommentInput from "components/common/CommentInput"; +import IssueCategoryList from "components/common/IssueCategoryList"; + +const NewIssueInput = () => { + return ( +
+
이슈 제목입력
+ +
+ ); +}; + +export default NewIssueInput; diff --git a/frontend/src/components/common/CancelButton.jsx b/frontend/src/components/common/CancelButton.jsx new file mode 100644 index 000000000..b65fb566e --- /dev/null +++ b/frontend/src/components/common/CancelButton.jsx @@ -0,0 +1,11 @@ +import { StyledCancelButton } from "styles/StyledButtons"; + +const CancelButton = ({ clickEvent, children }) => { + return ( + <> + {children} + + ); +}; + +export default CancelButton; diff --git a/frontend/src/components/common/CommentInput.jsx b/frontend/src/components/common/CommentInput.jsx index e69de29bb..9394fe070 100644 --- a/frontend/src/components/common/CommentInput.jsx +++ b/frontend/src/components/common/CommentInput.jsx @@ -0,0 +1,5 @@ +const CommentInput = () => { + return
이슈 코멘트 입력
; +}; + +export default CommentInput; diff --git a/frontend/src/components/common/Header.jsx b/frontend/src/components/common/Header.jsx index 9e9147573..217f14017 100644 --- a/frontend/src/components/common/Header.jsx +++ b/frontend/src/components/common/Header.jsx @@ -5,7 +5,6 @@ import getUserInfo from "util/getUserInfo"; const Header = () => { const userInfo = getUserInfo(); - console.log(userInfo); return ( diff --git a/frontend/src/components/common/IssueCategoryList.jsx b/frontend/src/components/common/IssueCategoryList.jsx index e69de29bb..596321373 100644 --- a/frontend/src/components/common/IssueCategoryList.jsx +++ b/frontend/src/components/common/IssueCategoryList.jsx @@ -0,0 +1,5 @@ +const IssueCategoryList = () => { + return
이슈 카테고리 리스트
; +}; + +export default IssueCategoryList; diff --git a/frontend/src/components/common/SubmitButton.jsx b/frontend/src/components/common/SubmitButton.jsx new file mode 100644 index 000000000..5dd81f196 --- /dev/null +++ b/frontend/src/components/common/SubmitButton.jsx @@ -0,0 +1,11 @@ +import { AddBtn } from "styles/StyledButtons"; + +const SubmitButton = ({ clickevent, children }) => { + return ( + <> + {children} + + ); +}; + +export default SubmitButton; diff --git a/frontend/src/components/pages/NewIssuePage.jsx b/frontend/src/components/pages/NewIssuePage.jsx index 8bdf5c530..d3e702988 100644 --- a/frontend/src/components/pages/NewIssuePage.jsx +++ b/frontend/src/components/pages/NewIssuePage.jsx @@ -1,5 +1,19 @@ +import styled from "styled-components"; +import NewIssueForm from "components/NewIssues/NewIssueForm"; + function NewIssue() { - return
새로운 이슈 쓰기 페이지
; + return ( + <> +
새로운 이슈 작성
+ + + ); } export default NewIssue; + +const Header = styled.div` + border-bottom: 1px solid ${({ theme }) => theme.grayScale.line}; + padding: ${({ theme }) => `${theme.fontSizes.titleSize} 0px`}; + font-size: ${({ theme }) => theme.fontSizes.titleSize}; +`; diff --git a/frontend/src/styles/StyledButtons.jsx b/frontend/src/styles/StyledButtons.jsx index dbacc709d..21350b8d1 100644 --- a/frontend/src/styles/StyledButtons.jsx +++ b/frontend/src/styles/StyledButtons.jsx @@ -35,7 +35,7 @@ export const AddBtn = styled(Button)` font-weight: bold; background-color: ${({ theme }) => theme.colors.blue}; color: ${({ theme }) => theme.grayScale.off_white}; - border: 1px solid ${({ theme }) => theme.grayScale.label}; + /* border: 1px solid ${({ theme }) => theme.grayScale.label}; */ border-radius: 11px; &:hover { background-color: ${({ theme }) => theme.colors.dark_blue}; @@ -53,3 +53,12 @@ export const StyledLoginButton = styled(Button)` background-color: ${({ theme }) => theme.grayScale.body}; } `; + +export const StyledCancelButton = styled(Button)` + width: ${props => props._width}; + height: ${({ theme }) => theme.buttonHeights.small}; + color: ${({ theme }) => theme.grayScale.label}; + font-weight: bold; + font-size: ${({ theme }) => theme.fontSizes.xs}; + border-radius: ${({ theme }) => theme.border_radius.small}; +`; diff --git a/frontend/src/styles/theme.js b/frontend/src/styles/theme.js index 5040ecb78..666cac283 100644 --- a/frontend/src/styles/theme.js +++ b/frontend/src/styles/theme.js @@ -27,7 +27,7 @@ const fontSizes = { xl: calcRem(20), xxl: calcRem(22), xxxl: calcRem(24), - titleSize: calcRem(50), + titleSize: calcRem(32), }; const paddings = { diff --git a/frontend/src/util/getUserInfo.js b/frontend/src/util/getUserInfo.js index 311954a84..782cbe653 100644 --- a/frontend/src/util/getUserInfo.js +++ b/frontend/src/util/getUserInfo.js @@ -1,11 +1,8 @@ const getUserInfo = () => { const token = localStorage.getItem("accessToken"); - console.log(token.split(".")[1]); const parsedToken = atob(token.split(".")[1]); - const { nickName, imageUrl, gitHubId, iss, id, exp } = JSON.parse( - parsedToken - ); - console.log(nickName, imageUrl, gitHubId, iss, id, exp); + const { nickName, imageUrl, gitHubId, iss, id, exp } = + JSON.parse(parsedToken); return { nickName, imageUrl, gitHubId, iss, id, exp }; }; From 9c3863c8dc267dbb01e3a575627b4592c690ac4c Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Wed, 16 Jun 2021 23:24:29 +0900 Subject: [PATCH 26/71] =?UTF-8?q?feat:=20=ED=95=AD=EB=AA=A9=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EB=B0=8F=20=EB=AA=A9=EB=A1=9D=20=ED=97=A4=EB=8D=94?= =?UTF-8?q?=20=EC=B6=94=EC=83=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/styles/StyledCards.jsx | 20 ++++++++++++++++++++ frontend/src/util/getGridRateStyle.js | 7 +++++++ 2 files changed, 27 insertions(+) create mode 100644 frontend/src/styles/StyledCards.jsx create mode 100644 frontend/src/util/getGridRateStyle.js diff --git a/frontend/src/styles/StyledCards.jsx b/frontend/src/styles/StyledCards.jsx new file mode 100644 index 000000000..45f2fdbc8 --- /dev/null +++ b/frontend/src/styles/StyledCards.jsx @@ -0,0 +1,20 @@ +import styled from "styled-components"; +import { getGridRateStyle } from "util/getGridRateStyle"; + +export const StyledGridTitleCard = styled.div` + display: grid; + align-items: center; + height: 64px; + border: 1px solid ${({ theme }) => theme.grayScale.line}; + border-radius: ${({ theme }) => theme.border_radius.lg} + ${({ theme }) => theme.border_radius.lg} 0px 0px; + grid-template-columns: ${props => getGridRateStyle(props.gridRate)}; +`; + +export const StyledGridCard = styled.div` + display: grid; + grid-template-columns: ${props => getGridRateStyle(props.gridRate)}; + background-color: ${({ theme }) => theme.grayScale.off_white}; + border: 1px solid ${({ theme }) => theme.grayScale.line}; + height: 100px; +`; diff --git a/frontend/src/util/getGridRateStyle.js b/frontend/src/util/getGridRateStyle.js new file mode 100644 index 000000000..d6b15f6ef --- /dev/null +++ b/frontend/src/util/getGridRateStyle.js @@ -0,0 +1,7 @@ +export const getGridRateStyle = gridRateArr => { + let result = ""; + gridRateArr.forEach(el => { + result += el + "fr "; + }); + return result; +}; From e959745f2d5ec210adabd2e3d0d6ca1cff20fab5 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Wed, 16 Jun 2021 23:24:55 +0900 Subject: [PATCH 27/71] =?UTF-8?q?feat:=20=EB=9D=BC=EB=B2=A8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20HTML=20=EA=B5=AC=EC=A1=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Issues/IssueList/IssueCard.jsx | 13 +++--------- .../Issues/IssueList/IssuesHeader.jsx | 14 +++---------- .../src/components/Issues/Menu/MenuTab.jsx | 9 +++++++-- frontend/src/components/Labels/LabelCard.jsx | 13 ++++++++++++ frontend/src/components/Labels/Labels.jsx | 13 +++++++++++- .../src/components/Labels/LabelsHeader.jsx | 10 ++++++++++ .../src/components/common/ButtonGroup.jsx | 9 +++++++-- frontend/src/components/common/Navigator.jsx | 20 ++++++++++++++++++- frontend/src/components/pages/LabelsPage.jsx | 13 +++++++++++- frontend/src/components/pages/MainPage.jsx | 13 ++++++------ .../src/components/pages/MilestonesPage.jsx | 15 +++++++++++++- 11 files changed, 106 insertions(+), 36 deletions(-) create mode 100644 frontend/src/components/Labels/LabelsHeader.jsx diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index e86e940f3..60e069acc 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -10,6 +10,7 @@ import getTimeStamp from "util/getTimeStamp"; // import { selectedIssueCntAtomState } from "MyRecoil/atom"; import { selectedIssueCntAtomState } from "RecoilStore/Atoms"; import { useRecoilState } from "recoil"; +import { StyledGridCard } from "styles/StyledCards"; const IssueCard = ({ issue, @@ -53,7 +54,7 @@ const IssueCard = ({ }, [isAllIssueSelected]); return ( - +
-
@@ -86,20 +87,12 @@ const IssueCard = ({ -
+ ); }; export default IssueCard; -const StyleCard = styled.div` - display: grid; - grid-template-columns: 0.5fr 9fr 0.6fr; - background-color: ${theme.grayScale.off_white}; - border: 1px solid ${theme.grayScale.line}; - height: 100px; -`; - const CheckBox = styled.div` display: flex; justify-content: space-evenly; diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index 38ca9db02..cf7d8b2ad 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -7,6 +7,7 @@ import theme from "styles/theme"; import DropDownButton from "components/common/DropDownButton"; import FilterModal from "components/common/FilterModal"; import { filter } from "data"; +import { StyledGridTitleCard } from "styles/StyledCards"; // import { selectedIssueCntAtomState, clickedFilterAtomState } from "MyRecoil/atom"; // import { useRecoilState } from "MyRecoil"; @@ -73,7 +74,7 @@ const IssuesHeader = ({ }, [selectedIssues]); return ( - + @@ -126,21 +127,12 @@ const IssuesHeader = ({
)} - + ); }; export default IssuesHeader; -const StyledIssuesHeader = styled.div` - display: grid; - align-items: center; - height: 64px; - border: 1px solid ${theme.grayScale.line}; - border-radius: ${theme.border_radius.lg} ${theme.border_radius.lg} 0px 0px; - grid-template-columns: 0.5fr 1.5fr 8.3fr; -`; - const FilterOpenClose = styled.div` display: flex; justify-content: space-between; diff --git a/frontend/src/components/Issues/Menu/MenuTab.jsx b/frontend/src/components/Issues/Menu/MenuTab.jsx index 87e80b21b..3f3f8f13b 100644 --- a/frontend/src/components/Issues/Menu/MenuTab.jsx +++ b/frontend/src/components/Issues/Menu/MenuTab.jsx @@ -1,15 +1,20 @@ +import styled from "styled-components"; import ButtonGroup from "components/common/ButtonGroup"; import AddButton from "components/common/AddButton"; import { Link } from "react-router-dom"; const MenuTab = () => { return ( -
+ -
+ ); }; +const Wrapper = styled.div` + display: flex; +`; + export default MenuTab; diff --git a/frontend/src/components/Labels/LabelCard.jsx b/frontend/src/components/Labels/LabelCard.jsx index e69de29bb..821993b97 100644 --- a/frontend/src/components/Labels/LabelCard.jsx +++ b/frontend/src/components/Labels/LabelCard.jsx @@ -0,0 +1,13 @@ +import { StyledGridCard } from "styles/StyledCards"; + +const LabelCard = () => { + return ( + +
레이블딱지
+
레이블 설명
+
편집 혹은 삭제
+
+ ); +}; + +export default LabelCard; diff --git a/frontend/src/components/Labels/Labels.jsx b/frontend/src/components/Labels/Labels.jsx index 3b82caeef..eaae4385c 100644 --- a/frontend/src/components/Labels/Labels.jsx +++ b/frontend/src/components/Labels/Labels.jsx @@ -1,5 +1,16 @@ +import LabelsHeader from "./LabelsHeader"; +import LabelCard from "./LabelCard"; +import LabelInput from "./LabelInput"; + const Labels = () => { - return
레이블
; + return ( + <> + + + + + + ); }; export default Labels; diff --git a/frontend/src/components/Labels/LabelsHeader.jsx b/frontend/src/components/Labels/LabelsHeader.jsx new file mode 100644 index 000000000..8336b9b2c --- /dev/null +++ b/frontend/src/components/Labels/LabelsHeader.jsx @@ -0,0 +1,10 @@ +import { StyledGridTitleCard } from "styles/StyledCards"; +const LabelsHeader = () => { + return ( + +
3개의 레이블
+
+ ); +}; + +export default LabelsHeader; diff --git a/frontend/src/components/common/ButtonGroup.jsx b/frontend/src/components/common/ButtonGroup.jsx index 3fdb2b656..931f39a5f 100644 --- a/frontend/src/components/common/ButtonGroup.jsx +++ b/frontend/src/components/common/ButtonGroup.jsx @@ -17,7 +17,7 @@ const ButtonGroup = ({ buttonText, }) => { return ( - <> + 레이블 ({labelCount}) - + ); }; +const Wrapper = styled.div` + display: flex; + justify-content: center; +`; + const ButtonText = styled.div` padding: 0 4%; `; diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index 83e411001..997cb5855 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -1,5 +1,23 @@ +import styled from "styled-components"; +import ButtonGroup from "./ButtonGroup"; +import AddButton from "./AddButton"; const Navigator = () => { - return
네비게이터
; + return ( + + {}} + labelCount={3} + labelClickEvent={() => {}} + /> + {}} /> + + ); }; export default Navigator; + +const Wrapper = styled.div` + display: flex; + justify-content: space-between; +`; diff --git a/frontend/src/components/pages/LabelsPage.jsx b/frontend/src/components/pages/LabelsPage.jsx index 61ed9bd07..06e8aa3db 100644 --- a/frontend/src/components/pages/LabelsPage.jsx +++ b/frontend/src/components/pages/LabelsPage.jsx @@ -1,5 +1,16 @@ +import styled from "styled-components"; +import Navigator from "components/common/Navigator"; +import Labels from "components/Labels/Labels"; + const LabelsPage = () => { - return
라벨페이지
; + return ( + + + + + ); }; export default LabelsPage; + +const Wrapper = styled.div``; diff --git a/frontend/src/components/pages/MainPage.jsx b/frontend/src/components/pages/MainPage.jsx index 909793b5c..ae89fbe67 100644 --- a/frontend/src/components/pages/MainPage.jsx +++ b/frontend/src/components/pages/MainPage.jsx @@ -4,8 +4,10 @@ import styled from "styled-components"; import NewIssue from "./NewIssuePage"; import NoMatch from "./NoMatchPage"; import IssueDetailPage from "./IssueDetailPage"; -import Labels from "components/Labels/Labels"; -import Milestones from "components/Milestones/Milestones"; +// import Labels from "components/Labels/Labels"; +import LabelsPage from "./LabelsPage"; +// import Milestones from "components/Milestones/Milestones"; +import MilestonesPage from "./MilestonesPage"; import Header from "components/common/Header"; import Navigator from "components/common/Navigator"; import Issues from "components/Issues/Issues"; @@ -16,13 +18,10 @@ const MainPage = () => { return localStorage.getItem("accessToken") ? (
- {(pathname === "/main/labels" || pathname === "/main/milestones") && ( - - )} {pathname === "/main" && } - - + + diff --git a/frontend/src/components/pages/MilestonesPage.jsx b/frontend/src/components/pages/MilestonesPage.jsx index e5aab1987..6c2d7f425 100644 --- a/frontend/src/components/pages/MilestonesPage.jsx +++ b/frontend/src/components/pages/MilestonesPage.jsx @@ -1,5 +1,18 @@ +import styled from "styled-components"; +import Navigator from "components/common/Navigator"; +import Milestones from "components/Milestones/Milestones"; + const MilestonesPage = () => { - return
마일스톤페이지
; + return ( +
+ + + + +
+ ); }; export default MilestonesPage; + +const Wrapper = styled.div``; From a0a35b87449d371b2378442a72ccf2799143800e Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Wed, 16 Jun 2021 23:34:54 +0900 Subject: [PATCH 28/71] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4=20=ED=8E=98=EC=9D=B4=EC=A7=80=20HTML=20=ED=8B=80=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelsHeader.jsx | 2 +- frontend/src/components/Milestones/MilestoneCard.jsx | 11 +++++++++++ frontend/src/components/Milestones/Milestones.jsx | 11 ++++++++++- .../src/components/Milestones/MilestonesHeader.jsx | 12 ++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 frontend/src/components/Milestones/MilestonesHeader.jsx diff --git a/frontend/src/components/Labels/LabelsHeader.jsx b/frontend/src/components/Labels/LabelsHeader.jsx index 8336b9b2c..f05584dea 100644 --- a/frontend/src/components/Labels/LabelsHeader.jsx +++ b/frontend/src/components/Labels/LabelsHeader.jsx @@ -2,7 +2,7 @@ import { StyledGridTitleCard } from "styles/StyledCards"; const LabelsHeader = () => { return ( -
3개의 레이블
+
N개의 레이블
); }; diff --git a/frontend/src/components/Milestones/MilestoneCard.jsx b/frontend/src/components/Milestones/MilestoneCard.jsx index e69de29bb..50d669e44 100644 --- a/frontend/src/components/Milestones/MilestoneCard.jsx +++ b/frontend/src/components/Milestones/MilestoneCard.jsx @@ -0,0 +1,11 @@ +import { StyledGridCard } from "styles/StyledCards"; +const MilestoneCard = () => { + return ( + +
마일스톤 정보
+
마일스톤 편집
+
+ ); +}; + +export default MilestoneCard; diff --git a/frontend/src/components/Milestones/Milestones.jsx b/frontend/src/components/Milestones/Milestones.jsx index 33a85980c..b6edc3d15 100644 --- a/frontend/src/components/Milestones/Milestones.jsx +++ b/frontend/src/components/Milestones/Milestones.jsx @@ -1,5 +1,14 @@ +import MilestonesHeader from "./MilestonesHeader"; +import MilestoneCard from "./MilestoneCard"; const Milestones = () => { - return
마일스톤
; + return ( + <> + + + + + + ); }; export default Milestones; diff --git a/frontend/src/components/Milestones/MilestonesHeader.jsx b/frontend/src/components/Milestones/MilestonesHeader.jsx new file mode 100644 index 000000000..d98907635 --- /dev/null +++ b/frontend/src/components/Milestones/MilestonesHeader.jsx @@ -0,0 +1,12 @@ +import { StyledGridTitleCard } from "styles/StyledCards"; + +const MilestonesHeader = () => { + return ( + +
열린 마일스톤(N)
+
닫힌 마일스톤(N)
+
+ ); +}; + +export default MilestonesHeader; From 0f3af80df6e6c8a35d0b541dd889e9426dc7c78e Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Wed, 16 Jun 2021 23:35:06 +0900 Subject: [PATCH 29/71] =?UTF-8?q?style:=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=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 72 +------------------ .../components/Issues/IssueList/IssueCard.jsx | 2 +- .../Issues/IssueList/IssuesHeader.jsx | 1 - .../components/Issues/Menu/MenuFilterBar.jsx | 39 ++++------ .../src/components/common/ButtonGroup.jsx | 7 +- .../src/components/common/DropDownButton.jsx | 1 - frontend/src/components/common/Header.jsx | 2 +- frontend/src/components/pages/MainPage.jsx | 3 +- frontend/src/styles/StyledButtons.jsx | 9 --- frontend/src/util/getUserInfo.js | 2 - 10 files changed, 20 insertions(+), 118 deletions(-) diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 1bc6419df..f568d60fc 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -1,4 +1,4 @@ -import { atom, selector } from "recoil"; +import { atom } from "recoil"; export const selectedIssueCntAtomState = atom({ key: "selectedIssueCntAtomState", @@ -10,31 +10,6 @@ export const clickedFilterAtomState = atom({ default: null, }); -export const assigneeFilterAtomState = atom({ - key: "assigneeFilterAtomState", - default: null, -}); - -export const labelFilterAtomState = atom({ - key: "labelFilterAtomState", - default: null, -}); - -export const milestoneFilterAtomState = atom({ - key: "milestoneFilterAtomState", - default: null, -}); - -export const authorFilterAtomState = atom({ - key: "authorFilterAtomState", - default: null, -}); - -export const issueFilterAtomState = atom({ - key: "issueFilterAtomState", - default: null, -}); - export const filterBarInputAtomState = atom({ key: "filterBarInputAtomState", default: { @@ -46,48 +21,3 @@ export const filterBarInputAtomState = atom({ issue: null, }, }); - -// export const filterBarInputAtomState = selector({ -// key: "filterBarInputAtomState", -// get: ({ get }) => { -// const placeholder = "is:issue is:open"; -// const assignee = get(assigneeFilterAtomState); -// const label = get(labelFilterAtomState); -// const milestone = get(milestoneFilterAtomState); -// const author = get(authorFilterAtomState); -// const issue = get(issueFilterAtomState); -// const filters = [placeholder, assignee, label, milestone, author, issue]; -// console.log("assignee", assignee); -// console.log(filters); -// return filters.reduce((acc, item) => { -// if (item) acc += item; -// return acc; -// }, ""); -// }, -// set: ({ set }, filterType) => { -// switch (filterType) { -// case "담당자": { -// set(assigneeFilterAtomState, clickedFilterAtomState); -// break; -// } -// case "레이블": { -// set(labelFilterAtomState, clickedFilterAtomState); -// break; -// } -// case "마일스톤": { -// set(milestoneFilterAtomState, clickedFilterAtomState); -// break; -// } -// case "작성자": { -// set(authorFilterAtomState, clickedFilterAtomState); -// break; -// } -// case "필터": { -// set(issueFilterAtomState, clickedFilterAtomState); -// break; -// } -// default: -// throw new Error("Unhandled Type"); -// } -// }, -// }); diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index e86e940f3..f6a7e1db5 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -35,7 +35,7 @@ const IssueCard = ({ setSelectedCards(selectedCards.add(id)); } }; - console.log(selectedCards); + // console.log(selectedCards); // console.log(selectedIssues); useEffect(() => { isChecked ? setIsAnyIssueSelected(true) : setIsAnyIssueSelected(false); diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index 38ca9db02..9ddbd4240 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -114,7 +114,6 @@ const IssuesHeader = ({ className={"issue-header-button"} width={({ theme }) => theme.buttonWidths.small} border={"none"} - id={filter} > ))} diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index 50bd92290..600c43cc0 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -3,7 +3,7 @@ import { ReactComponent as SearchIcon } from "images/search.svg"; import DropDownButton from "components/common/DropDownButton"; import theme from "styles/theme"; import FilterModal from "components/common/FilterModal"; -import { useState, useEffect, useCallback } from "react"; +import { useState, useEffect } from "react"; import { clickedFilterAtomState, filterBarInputAtomState, @@ -20,17 +20,16 @@ const MenuFilterBar = () => { if (item[0] === "placeholder") acc += `${item[1]} `; else acc += `${item[0]}:${item[1]} `; } - console.log(acc); return acc; }, ""); }; - const handleClick = useCallback(e => { + const handleClick = e => { isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); setClickedFilterState(e.target.textContent); - }); + }; useEffect(() => { window.addEventListener("click", closeFilterModal); @@ -44,6 +43,7 @@ const MenuFilterBar = () => { if (isFilterClicked && !target.closest(".filter-modal")) setIsFilterClicked(false); }; + const handleInputChange = () => {}; return ( <> @@ -54,15 +54,12 @@ const MenuFilterBar = () => { width={({ theme }) => theme.buttonWidths.base} radius={"left"} /> + - - - - - - + + + + {getFilterBarString(filterBarInput)} {isFilterClicked && } @@ -77,26 +74,20 @@ const MenuFilterLayout = styled.div` position: relative; margin-bottom: 24px; `; + const FilterInputContainer = styled.div` - width: 100%; - height: 100%; - border: 1px solid ${theme.grayScale.line}; - border-radius: ${theme.border_radius_mix.right}; -`; -const FilterInput = styled.div` display: flex; width: 100%; height: 100%; - padding: 0; + padding: 11px; + border: 1px solid ${theme.grayScale.line}; background-color: ${theme.grayScale.input_background}; border-radius: ${theme.border_radius_mix.right}; `; -const FilterInputIconContainer = styled.div` - padding: 11px; -`; -const FilterInputText = styled.input` +const FilterInputIconContainer = styled.div``; +const FilterInput = styled.div` width: 100%; - height: 100%; + padding-left: 10px; border: none; background-color: ${theme.grayScale.input_background}; color: ${theme.grayScale.placeholder}; diff --git a/frontend/src/components/common/ButtonGroup.jsx b/frontend/src/components/common/ButtonGroup.jsx index 3fdb2b656..f4362c350 100644 --- a/frontend/src/components/common/ButtonGroup.jsx +++ b/frontend/src/components/common/ButtonGroup.jsx @@ -1,8 +1,4 @@ -import { - ButtonGroupLeftBtn, - ButtonGroupRightBtn, - TabButton, -} from "styles/StyledButtons"; +import { TabButton } from "styles/StyledButtons"; import styled from "styled-components"; import { ReactComponent as LabelIcon } from "images/tag.svg"; import { ReactComponent as MileStoneIcon } from "images/milestone.svg"; @@ -14,7 +10,6 @@ const ButtonGroup = ({ milestoneClickEvent, labelCount, labelClickEvent, - buttonText, }) => { return ( <> diff --git a/frontend/src/components/common/DropDownButton.jsx b/frontend/src/components/common/DropDownButton.jsx index 841fa4305..32b85f60c 100644 --- a/frontend/src/components/common/DropDownButton.jsx +++ b/frontend/src/components/common/DropDownButton.jsx @@ -20,7 +20,6 @@ const DropDownButton = ({ text, clickEvent, width, border, radius }) => { }; const ButtonText = styled.div` - /* outline: red 1px solid; */ padding-right: 30%; `; export default DropDownButton; diff --git a/frontend/src/components/common/Header.jsx b/frontend/src/components/common/Header.jsx index c10495210..f8297ab64 100644 --- a/frontend/src/components/common/Header.jsx +++ b/frontend/src/components/common/Header.jsx @@ -5,7 +5,7 @@ import getUserInfo from "util/getUserInfo"; const Header = () => { const userInfo = getUserInfo(); - console.log(userInfo); + return ( diff --git a/frontend/src/components/pages/MainPage.jsx b/frontend/src/components/pages/MainPage.jsx index 1a59fd4b2..3c040bed2 100644 --- a/frontend/src/components/pages/MainPage.jsx +++ b/frontend/src/components/pages/MainPage.jsx @@ -1,5 +1,4 @@ -import { useState } from "react"; -import { Route, Switch, Link, Redirect } from "react-router-dom"; +import { Route, Switch, Redirect } from "react-router-dom"; import styled from "styled-components"; import NewIssue from "./NewIssuePage"; import NoMatch from "./NoMatchPage"; diff --git a/frontend/src/styles/StyledButtons.jsx b/frontend/src/styles/StyledButtons.jsx index dbacc709d..baabaa8f0 100644 --- a/frontend/src/styles/StyledButtons.jsx +++ b/frontend/src/styles/StyledButtons.jsx @@ -19,15 +19,6 @@ export const TabButton = styled(Button)` theme.grayScale.background}; //str넣었는데 str넣으라고 오류뜸 `; -export const ButtonGroupRightBtn = styled(TabButton)` - border-radius: ${({ theme }) => theme.border_radius_mix.right}; - width: ${({ theme }) => theme.buttonWidths.base}; -`; - -export const ButtonGroupLeftBtn = styled(TabButton)` - border-radius: ${({ theme }) => theme.border_radius_mix.left}; -`; - export const AddBtn = styled(Button)` width: 160px; height: ${({ theme }) => theme.buttonHeights.base}; diff --git a/frontend/src/util/getUserInfo.js b/frontend/src/util/getUserInfo.js index 311954a84..402709f9b 100644 --- a/frontend/src/util/getUserInfo.js +++ b/frontend/src/util/getUserInfo.js @@ -1,11 +1,9 @@ const getUserInfo = () => { const token = localStorage.getItem("accessToken"); - console.log(token.split(".")[1]); const parsedToken = atob(token.split(".")[1]); const { nickName, imageUrl, gitHubId, iss, id, exp } = JSON.parse( parsedToken ); - console.log(nickName, imageUrl, gitHubId, iss, id, exp); return { nickName, imageUrl, gitHubId, iss, id, exp }; }; From c650f6eff5aaf5ef540311457ac5ad058510302d Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Wed, 16 Jun 2021 23:35:54 +0900 Subject: [PATCH 30/71] =?UTF-8?q?feat:=20filterModal=20radio=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=B2=B4=ED=81=AC=20=ED=95=B4=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=99=84=EC=84=B1(#29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/common/FilterModal.jsx | 68 ++++++++----------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index ba8c16e4e..28ddea844 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -1,78 +1,72 @@ -import { useEffect } from "react"; +import { useState } from "react"; +import { + filterBarInputAtomState, + clickedFilterAtomState, +} from "RecoilStore/Atoms"; +import { useRecoilValue, useRecoilState } from "recoil"; +import styled from "styled-components"; + import Radio from "@material-ui/core/Radio"; import RadioGroup from "@material-ui/core/RadioGroup"; import FormControlLabel from "@material-ui/core/FormControlLabel"; import FormControl from "@material-ui/core/FormControl"; import FormLabel from "@material-ui/core/FormLabel"; -import { useState } from "react"; -import styled from "styled-components"; import { filter } from "data"; -import { - filterBarInputAtomState, - clickedFilterAtomState, -} from "RecoilStore/Atoms"; -import { useRecoilValue, useSetRecoilState, useRecoilState } from "recoil"; + import getEngKey from "util/getEngKey"; -{ - /* 클릭된게 어떤 필터인지를 modal이 알아야 함 useRecoilState 쓰려다 오류나서 state내림 */ -} + const FilterModal = () => { - const [value, setValue] = useState(""); + const [clickedFilterState, setClickedFilterState] = useState(""); const filterType = useRecoilValue(clickedFilterAtomState); const [filterBarInputState, setFilterBarInputState] = useRecoilState( filterBarInputAtomState ); - // Recoil로직 (구현 예정) - // 1. 필터별로 선택된 필터는 atom으로 관리됨(default는 null임) - // 2. 이슈리스트 필터링, 검색창에 현재 선택된 ent.target.value); - //필터들 보여줄 때는 그 Atom의 조합으로 보여줌 (특히 검색창엔 selector이용해서 붙이면 간단할듯) - - // - + const key = getEngKey(filterType); const handleChange = event => { - setValue(event.target.value); + setClickedFilterState(event.target.value); setFilterStateByType(event.target.value); }; - const key = getEngKey(filterType); + const setFilterStateByType = clickedValue => { + const updatedValue = + clickedValue === filterBarInputState[getEngKey(filterType)] + ? null + : clickedValue; - const setFilterStateByType = value => { - // console.log(filterType); switch (filterType) { case "담당자": { - console.log("담당자,filterBarInputState"); setFilterBarInputState({ ...filterBarInputState, - assignee: value, + assignee: updatedValue, }); break; } case "레이블": { setFilterBarInputState({ ...filterBarInputState, - label: value, + label: updatedValue, }); break; } case "마일스톤": { setFilterBarInputState({ ...filterBarInputState, - milestone: value, + milestone: updatedValue, }); break; } case "작성자": { setFilterBarInputState({ ...filterBarInputState, - author: value, + author: updatedValue, }); break; } case "필터": { setFilterBarInputState({ ...filterBarInputState, - issue: value, + issue: updatedValue, }); break; } @@ -82,12 +76,8 @@ const FilterModal = () => { } }; - const getFilterModalData = type => { - return filter[getEngKey(type)]; - }; + const filterData = filter[getEngKey(filterType)]; - const filterData = getFilterModalData(filterType); - console.log(filterData); return ( @@ -97,8 +87,8 @@ const FilterModal = () => { {filterData && filterData.map((text, idx) => ( @@ -107,8 +97,8 @@ const FilterModal = () => { control={} label={text} labelPlacement="start" - key={idx} - checked={filterBarInputState[key] === text} // + key={`filter-control-label-${idx}`} + checked={filterBarInputState[key] === text} /> ))} @@ -116,6 +106,7 @@ const FilterModal = () => { ); }; + const FilterModalLayout = styled.div` position: absolute; top: 45px; @@ -134,6 +125,7 @@ const FilterControlLabel = styled(FormControlLabel)` const FilterRadioContainer = styled(RadioGroup)` padding: 8px 16px; `; + const FilterTitle = styled(FormLabel)` background-color: ${({ theme }) => theme.grayScale.background}; width: 100%; From 0616eb4fcbdfda937965055c845ec17f86ac2cc5 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Wed, 16 Jun 2021 23:38:58 +0900 Subject: [PATCH 31/71] =?UTF-8?q?chore:=20=EA=B0=92=20=EC=97=86=EB=8A=94?= =?UTF-8?q?=20Prop=20N=EC=9C=BC=EB=A1=9C=20=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/common/Navigator.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index 997cb5855..d714934a5 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -5,9 +5,9 @@ const Navigator = () => { return ( {}} - labelCount={3} + labelCount={"N"} labelClickEvent={() => {}} /> {}} /> From 6ac8fc4d1ac2a6ca44755c340b8a029f3fde4919 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Thu, 17 Jun 2021 12:15:20 +0900 Subject: [PATCH 32/71] =?UTF-8?q?WIP:=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4=20=EC=B9=B4=EB=93=9C=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Milestones/MilestoneCard.jsx | 53 +++++++++++++++++-- .../Milestones/MilestonesHeader.jsx | 34 +++++++++++- frontend/src/styles/StyledCards.jsx | 8 +++ frontend/src/styles/theme.js | 6 +++ 4 files changed, 94 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/Milestones/MilestoneCard.jsx b/frontend/src/components/Milestones/MilestoneCard.jsx index 50d669e44..0ebe39628 100644 --- a/frontend/src/components/Milestones/MilestoneCard.jsx +++ b/frontend/src/components/Milestones/MilestoneCard.jsx @@ -1,11 +1,54 @@ -import { StyledGridCard } from "styles/StyledCards"; +import styled from "styled-components"; +import { StyledFlexCard } from "styles/StyledCards"; const MilestoneCard = () => { return ( - -
마일스톤 정보
-
마일스톤 편집
-
+ + + +
+ 마일스톤 제목 + 완료일 일정 +
+
마일스톤에 대한 설명
+
+ +
+ 편집 + 삭제 +
+
+
프로그레스바
+ +
00%
+
열린 이슈 N 닫힌 이슈 N
+
+
+
+
+
); }; export default MilestoneCard; + +const Info = styled.div` + display: flex; + flex-direction: column; + justify-content: space-evenly; +`; + +const Edit = styled.div` + display: flex; + flex-direction: column; + justify-content: space-evenly; +`; + +const Detail = styled.div` + display: flex; +`; + +const ContentsWrapper = styled.div` + display: flex; + justify-content: space-between; + width: 97%; +`; diff --git a/frontend/src/components/Milestones/MilestonesHeader.jsx b/frontend/src/components/Milestones/MilestonesHeader.jsx index d98907635..3b3e9b001 100644 --- a/frontend/src/components/Milestones/MilestonesHeader.jsx +++ b/frontend/src/components/Milestones/MilestonesHeader.jsx @@ -1,12 +1,42 @@ +import { useState } from "react"; +import styled from "styled-components"; import { StyledGridTitleCard } from "styles/StyledCards"; +import { ReactComponent as MilestoneIcon } from "images/milestone.svg"; +import { ReactComponent as ArchiveIcon } from "images/archive.svg"; +import theme from "styles/theme"; const MilestonesHeader = () => { + const [showOpenedOnes, setShowOpendOnes] = useState(true); + + const getColor = () => { + return showOpenedOnes ? "#000000" : `${theme.grayScale.label}`; + }; + return ( -
열린 마일스톤(N)
-
닫힌 마일스톤(N)
+ + + <MilestoneIcon fill={getColor()} /> + 열린 마일스톤(N) + + + <ArchiveIcon /> + 닫힌 마일스톤(N) + +
); }; export default MilestonesHeader; + +const Contents = styled.div` + display: flex; + justify-content: space-between; + width: 25%; + align-items: center; +`; + +const Title = styled.div` + padding: ${({ theme }) => `0 ${theme.paddings.xxxl}`}; +`; diff --git a/frontend/src/styles/StyledCards.jsx b/frontend/src/styles/StyledCards.jsx index 45f2fdbc8..8a5dc8213 100644 --- a/frontend/src/styles/StyledCards.jsx +++ b/frontend/src/styles/StyledCards.jsx @@ -18,3 +18,11 @@ export const StyledGridCard = styled.div` border: 1px solid ${({ theme }) => theme.grayScale.line}; height: 100px; `; + +export const StyledFlexCard = styled.div` + display: flex; + justify-content: center; + background-color: ${({ theme }) => theme.grayScale.off_white}; + border: 1px solid ${({ theme }) => theme.grayScale.line}; + height: 100px; +`; diff --git a/frontend/src/styles/theme.js b/frontend/src/styles/theme.js index 666cac283..a3a9cf433 100644 --- a/frontend/src/styles/theme.js +++ b/frontend/src/styles/theme.js @@ -88,6 +88,7 @@ const grayScale = { input_background: "#EFF0F6", background: "#F7F7FC", off_white: "#FEFEFE", + black: "#000000", }; const colors = { @@ -105,6 +106,10 @@ const colors = { dark_green: "#00A028", }; +const getColorByCondition = (condition, colorA, colorB) => { + return condition ? colorA : colorB; +}; + const device = { mobileS: `only screen and (max-width: ${deviceSizes.mobileS})`, mobileM: `only screen and (max-width: ${deviceSizes.mobileM})`, @@ -128,6 +133,7 @@ const theme = { StyledSpaceBetween, buttonWidths, buttonHeights, + getColorByCondition, }; export default theme; From 88c14e8e3c97cb4000919d75dfde0384943bce91 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Thu, 17 Jun 2021 14:44:55 +0900 Subject: [PATCH 33/71] =?UTF-8?q?fix:=20=EB=84=A4=EB=B9=84=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=84=EC=97=AD=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Issues/Menu/MenuFilterBar.jsx | 6 +++--- frontend/src/components/pages/LabelsPage.jsx | 9 ++------- frontend/src/components/pages/MainPage.jsx | 4 +++- frontend/src/components/pages/MilestonesPage.jsx | 13 +++---------- 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index 600c43cc0..2397bf294 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -13,7 +13,7 @@ const MenuFilterBar = () => { const [isFilterClicked, setIsFilterClicked] = useState(false); const setClickedFilterState = useSetRecoilState(clickedFilterAtomState); const filterBarInput = useRecoilValue(filterBarInputAtomState); - + console.log(filterBarInput); const getFilterBarString = () => { return Object.entries(filterBarInput).reduce((acc, item) => { if (item[1]) { @@ -24,7 +24,7 @@ const MenuFilterBar = () => { }, ""); }; - const handleClick = e => { + const handleClick = (e) => { isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); @@ -38,7 +38,7 @@ const MenuFilterBar = () => { }; }, [isFilterClicked]); - const closeFilterModal = e => { + const closeFilterModal = (e) => { const target = e.target; if (isFilterClicked && !target.closest(".filter-modal")) setIsFilterClicked(false); diff --git a/frontend/src/components/pages/LabelsPage.jsx b/frontend/src/components/pages/LabelsPage.jsx index 06e8aa3db..e9b642e7d 100644 --- a/frontend/src/components/pages/LabelsPage.jsx +++ b/frontend/src/components/pages/LabelsPage.jsx @@ -1,16 +1,11 @@ -import styled from "styled-components"; -import Navigator from "components/common/Navigator"; import Labels from "components/Labels/Labels"; const LabelsPage = () => { return ( - - + <> - + ); }; export default LabelsPage; - -const Wrapper = styled.div``; diff --git a/frontend/src/components/pages/MainPage.jsx b/frontend/src/components/pages/MainPage.jsx index 37f1f6ed4..471a87418 100644 --- a/frontend/src/components/pages/MainPage.jsx +++ b/frontend/src/components/pages/MainPage.jsx @@ -13,10 +13,12 @@ import Issues from "components/Issues/Issues"; const MainPage = () => { const { pathname } = window.location; - return localStorage.getItem("accessToken") ? (
+ {(pathname === "/main/labels" || pathname === "/main/milestones") && ( + + )} {pathname === "/main" && } diff --git a/frontend/src/components/pages/MilestonesPage.jsx b/frontend/src/components/pages/MilestonesPage.jsx index 6c2d7f425..d65e95d0f 100644 --- a/frontend/src/components/pages/MilestonesPage.jsx +++ b/frontend/src/components/pages/MilestonesPage.jsx @@ -1,18 +1,11 @@ -import styled from "styled-components"; -import Navigator from "components/common/Navigator"; import Milestones from "components/Milestones/Milestones"; const MilestonesPage = () => { return ( -
- - - - -
+ <> + + ); }; export default MilestonesPage; - -const Wrapper = styled.div``; From b4385b0f23098909992f1d93cb29592d28a19e26 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Thu, 17 Jun 2021 16:11:19 +0900 Subject: [PATCH 34/71] =?UTF-8?q?feat:=20=EB=A0=88=EC=9D=B4=EB=B8=94/?= =?UTF-8?q?=EB=A7=88=EC=9D=BC=EC=8A=A4=ED=86=A4=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=ED=83=AD=EB=B2=84=ED=8A=BC=20=EB=B0=B0=EA=B2=BD?= =?UTF-8?q?=ED=9A=A8=EA=B3=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/MyRecoil/atom.js | 28 +++++++-------- frontend/src/RecoilStore/Atoms.jsx | 28 ++++++++++----- .../components/Issues/IssueList/IssueCard.jsx | 6 ++-- .../components/Issues/IssueList/IssueList.jsx | 8 ++--- .../Issues/IssueList/IssuesHeader.jsx | 18 +++++----- .../components/Issues/Menu/MenuFilterBar.jsx | 9 ++--- .../src/components/Issues/Menu/MenuTab.jsx | 24 ++++++++++++- .../src/components/common/ButtonGroup.jsx | 13 +++++++ .../src/components/common/FilterModal.jsx | 34 ++++++++----------- frontend/src/components/common/Navigator.jsx | 22 ++++++++++-- frontend/src/components/pages/AnotherTest.jsx | 4 +-- frontend/src/components/pages/MainPage.jsx | 2 -- frontend/src/components/pages/Test.jsx | 9 +++-- frontend/src/styles/StyledButtons.jsx | 18 ++++++---- 14 files changed, 140 insertions(+), 83 deletions(-) diff --git a/frontend/src/MyRecoil/atom.js b/frontend/src/MyRecoil/atom.js index 75b36f254..8022e62a6 100644 --- a/frontend/src/MyRecoil/atom.js +++ b/frontend/src/MyRecoil/atom.js @@ -3,37 +3,37 @@ // // } // import { atom } from "./index"; -// export const issueAtomState = atom({ -// key: "issueAtomState", +// export const issueState = atom({ +// key: "issueState", // initialState: true, // }); -// export const milestoneAtomState = atom({ -// key: "milestoneAtomState", +// export const milestoneState = atom({ +// key: "milestoneState", // initialState: [], // }); -// export const asigneeAtomState = atom({ -// key: "asigneeAtomState", +// export const asigneeState = atom({ +// key: "asigneeState", // initialState: [], // }); -// export const labelAtomState = atom({ -// key: "labelAtomState", +// export const labelState = atom({ +// key: "labelState", // initialState: [], // }); -// export const authorAtomState = atom({ -// key: "authorAtomState", +// export const authorState = atom({ +// key: "authorState", // initialState: [], // }); -// export const selectedIssueCntAtomState = atom({ -// key: "selectedIssueCntAtomState", +// export const selectedIssueCntState = atom({ +// key: "selectedIssueCntState", // initialState: 0, // }); -// export const clickedFilterAtomState = atom({ -// key: "clickedFilterAtomState", +// export const clickedFilterState = atom({ +// key: "clickedFilterState", // initialState: null, // }); diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index f568d60fc..1cf540463 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -1,23 +1,33 @@ import { atom } from "recoil"; -export const selectedIssueCntAtomState = atom({ - key: "selectedIssueCntAtomState", +export const selectedIssueCntState = atom({ + key: "selectedIssueCntState", default: 0, }); -export const clickedFilterAtomState = atom({ - key: "clickedFilterAtomState", +export const clickedFilterState = atom({ + key: "clickedFilterState", default: null, }); -export const filterBarInputAtomState = atom({ - key: "filterBarInputAtomState", +export const filterBarInputState = atom({ + key: "filterBarInputState", default: { placeholder: "is:issue is:open", - assignee: null, // asignee 필터 모달 에서 마지막으로 클릭한 값이 저장 - label: null, // label 필터모달 에서 마지막으로 클릭한 값이 저장 - milestone: null, // "마일스톤": null + assignee: null, + label: null, + milestone: null, author: null, issue: null, }, }); + +export const labelButtonFlagState = atom({ + key: "labelButtonFlag", + default: false, +}); + +export const milestoneButtonFlagState = atom({ + key: "milestoneButtonFlag", + default: false, +}); diff --git a/frontend/src/components/Issues/IssueList/IssueCard.jsx b/frontend/src/components/Issues/IssueList/IssueCard.jsx index 7bced69c2..f6b64af90 100644 --- a/frontend/src/components/Issues/IssueList/IssueCard.jsx +++ b/frontend/src/components/Issues/IssueList/IssueCard.jsx @@ -7,8 +7,8 @@ import { ReactComponent as Alert } from "images/alert-circle.svg"; import { ReactComponent as Milestone } from "images/milestone.svg"; import getTimeStamp from "util/getTimeStamp"; // import { useRecoilState } from "MyRecoil"; -// import { selectedIssueCntAtomState } from "MyRecoil/atom"; -import { selectedIssueCntAtomState } from "RecoilStore/Atoms"; +// import { selectedIssueCntState } from "MyRecoil/atom"; +import { selectedIssueCntState } from "RecoilStore/Atoms"; import { useRecoilState } from "recoil"; import { StyledGridCard } from "styles/StyledCards"; @@ -22,7 +22,7 @@ const IssueCard = ({ }) => { const [isChecked, setIsChecked] = useState(false); const [selectedIssues, setSelectedIssues] = useRecoilState( - selectedIssueCntAtomState + selectedIssueCntState ); const { title, id, labelId, milestoneId, author, createdAt } = issue; const handleCheck = () => { diff --git a/frontend/src/components/Issues/IssueList/IssueList.jsx b/frontend/src/components/Issues/IssueList/IssueList.jsx index 09229940b..83154d7a2 100644 --- a/frontend/src/components/Issues/IssueList/IssueList.jsx +++ b/frontend/src/components/Issues/IssueList/IssueList.jsx @@ -3,15 +3,15 @@ import styled from "styled-components"; import IssuesHeader from "./IssuesHeader"; import IssueCard from "./IssueCard"; import { issues } from "data"; -// import { selectedIssueCntAtomState } from "MyRecoil/atom"; +// import { selectedIssueCntState } from "MyRecoil/atom"; import { useRecoilState } from "recoil"; -import { selectedIssueCntAtomState } from "RecoilStore/Atoms"; +import { selectedIssueCntState } from "RecoilStore/Atoms"; // import { useRecoilState } from "MyRecoil"; const IssueList = () => { const [isAnyIssueSelected, setIsAnyIssueSelected] = useState(false); // 상태 위치 협의 후 수정 const [isAllIssueSelected, setIsAllIssueSelected] = useState(false); - const [_, setSelectedIssues] = useRecoilState(selectedIssueCntAtomState); + const [_, setSelectedIssues] = useRecoilState(selectedIssueCntState); const [selectedCards, setSelectedCards] = useState(new Set()); useEffect(() => { @@ -19,7 +19,7 @@ const IssueList = () => { setSelectedIssues(() => 0); }, [isAnyIssueSelected]); - const issueList = issues.map(issue => ( + const issueList = issues.map((issue) => ( { const [selectedIssues, setSelectedIssues] = useRecoilState( - selectedIssueCntAtomState + selectedIssueCntState ); const buttonNames = ["담당자", "레이블", "마일스톤", "작성자"]; - const setClickedFilterState = useSetRecoilState(clickedFilterAtomState); - // const setFilterBarInputState = useSetRecoilState(filterBarInputAtomState); + const setClickedFilterState = useSetRecoilState(clickedFilterState); + // const setFilterBarInputState = useSetRecoilState(filterBarInputState); //----------중복 코드from MeuFilter -------- const [isFilterClicked, setIsFilterClicked] = useState(false); - const handleClick = useCallback(e => { + const handleClick = useCallback((e) => { isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); @@ -52,7 +52,7 @@ const IssuesHeader = ({ }; }, [isFilterClicked]); - const closeFilterModal = e => { + const closeFilterModal = (e) => { const target = e.target; if ( isFilterClicked && diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index 2397bf294..8462c0194 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -4,15 +4,12 @@ import DropDownButton from "components/common/DropDownButton"; import theme from "styles/theme"; import FilterModal from "components/common/FilterModal"; import { useState, useEffect } from "react"; -import { - clickedFilterAtomState, - filterBarInputAtomState, -} from "RecoilStore/Atoms"; +import { clickedFilterState, filterBarInputState } from "RecoilStore/Atoms"; import { useSetRecoilState, useRecoilValue } from "recoil"; const MenuFilterBar = () => { const [isFilterClicked, setIsFilterClicked] = useState(false); - const setClickedFilterState = useSetRecoilState(clickedFilterAtomState); - const filterBarInput = useRecoilValue(filterBarInputAtomState); + const setClickedFilterState = useSetRecoilState(clickedFilterState); + const filterBarInput = useRecoilValue(filterBarInputState); console.log(filterBarInput); const getFilterBarString = () => { return Object.entries(filterBarInput).reduce((acc, item) => { diff --git a/frontend/src/components/Issues/Menu/MenuTab.jsx b/frontend/src/components/Issues/Menu/MenuTab.jsx index 3f3f8f13b..40abb1d4c 100644 --- a/frontend/src/components/Issues/Menu/MenuTab.jsx +++ b/frontend/src/components/Issues/Menu/MenuTab.jsx @@ -2,10 +2,32 @@ import styled from "styled-components"; import ButtonGroup from "components/common/ButtonGroup"; import AddButton from "components/common/AddButton"; import { Link } from "react-router-dom"; +import { useSetRecoilState } from "recoil"; +import { + labelButtonFlagState, + milestoneButtonFlagState, +} from "RecoilStore/Atoms"; const MenuTab = () => { + const setMilestoneFlag = useSetRecoilState(milestoneButtonFlagState); + const setLabelFlag = useSetRecoilState(labelButtonFlagState); + + const handleMilestoneClick = () => { + setMilestoneFlag(true); + setLabelFlag(false); + }; + const handleLabelClick = () => { + setMilestoneFlag(false); + setLabelFlag(true); + }; return ( - + diff --git a/frontend/src/components/common/ButtonGroup.jsx b/frontend/src/components/common/ButtonGroup.jsx index 8bbb2959b..f3133d9cb 100644 --- a/frontend/src/components/common/ButtonGroup.jsx +++ b/frontend/src/components/common/ButtonGroup.jsx @@ -4,13 +4,22 @@ import { ReactComponent as LabelIcon } from "images/tag.svg"; import { ReactComponent as MileStoneIcon } from "images/milestone.svg"; import theme from "styles/theme"; import { Link } from "react-router-dom"; +import { useRecoilValue } from "recoil"; +import { + labelButtonFlagState, + milestoneButtonFlagState, +} from "RecoilStore/Atoms"; const ButtonGroup = ({ milestoneCount, milestoneClickEvent, labelCount, labelClickEvent, + isMainPage, }) => { + const milestoneFlag = useRecoilValue(milestoneButtonFlagState); + const labelFlag = useRecoilValue(labelButtonFlagState); + return ( @@ -18,6 +27,8 @@ const ButtonGroup = ({ onClick={milestoneClickEvent} _width={({ theme }) => theme.buttonWidths.base} _radius={"left"} + bgColor={milestoneFlag} + isMainPage={isMainPage} > 마일스톤 ({milestoneCount}) @@ -28,6 +39,8 @@ const ButtonGroup = ({ onClick={labelClickEvent} _width={({ theme }) => theme.buttonWidths.base} _radius={"right"} + bgColor={labelFlag} + isMainPage={isMainPage} > 레이블 ({labelCount}) diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index 28ddea844..48c3733ea 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -1,8 +1,5 @@ import { useState } from "react"; -import { - filterBarInputAtomState, - clickedFilterAtomState, -} from "RecoilStore/Atoms"; +import { filterBarInputState, clickedFilterState } from "RecoilStore/Atoms"; import { useRecoilValue, useRecoilState } from "recoil"; import styled from "styled-components"; @@ -16,56 +13,55 @@ import { filter } from "data"; import getEngKey from "util/getEngKey"; const FilterModal = () => { - const [clickedFilterState, setClickedFilterState] = useState(""); - const filterType = useRecoilValue(clickedFilterAtomState); - const [filterBarInputState, setFilterBarInputState] = useRecoilState( - filterBarInputAtomState - ); + const [clickedFilter, setClickedFilterState] = useState(""); + const filterType = useRecoilValue(clickedFilterState); + const [filterBarInput, setFilterBarInputState] = + useRecoilState(filterBarInputState); const key = getEngKey(filterType); - const handleChange = event => { + const handleChange = (event) => { setClickedFilterState(event.target.value); setFilterStateByType(event.target.value); }; - const setFilterStateByType = clickedValue => { + const setFilterStateByType = (clickedValue) => { const updatedValue = - clickedValue === filterBarInputState[getEngKey(filterType)] + clickedValue === filterBarInput[getEngKey(filterType)] ? null : clickedValue; switch (filterType) { case "담당자": { setFilterBarInputState({ - ...filterBarInputState, + ...filterBarInput, assignee: updatedValue, }); break; } case "레이블": { setFilterBarInputState({ - ...filterBarInputState, + ...filterBarInput, label: updatedValue, }); break; } case "마일스톤": { setFilterBarInputState({ - ...filterBarInputState, + ...filterBarInput, milestone: updatedValue, }); break; } case "작성자": { setFilterBarInputState({ - ...filterBarInputState, + ...filterBarInput, author: updatedValue, }); break; } case "필터": { setFilterBarInputState({ - ...filterBarInputState, + ...filterBarInput, issue: updatedValue, }); break; @@ -87,7 +83,7 @@ const FilterModal = () => { {filterData && @@ -98,7 +94,7 @@ const FilterModal = () => { label={text} labelPlacement="start" key={`filter-control-label-${idx}`} - checked={filterBarInputState[key] === text} + checked={filterBarInput[key] === text} /> ))} diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index d714934a5..68e4ae99c 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -1,14 +1,32 @@ import styled from "styled-components"; import ButtonGroup from "./ButtonGroup"; import AddButton from "./AddButton"; +import { useSetRecoilState } from "recoil"; +import { + labelButtonFlagState, + milestoneButtonFlagState, +} from "RecoilStore/Atoms"; + const Navigator = () => { + const setMilestoneFlag = useSetRecoilState(milestoneButtonFlagState); + const setLabelFlag = useSetRecoilState(labelButtonFlagState); + const handleMilestoneClick = () => { + setMilestoneFlag(true); + setLabelFlag(false); + }; + const handleLabelClick = () => { + setMilestoneFlag(false); + setLabelFlag(true); + }; + return ( {}} + milestoneClickEvent={handleMilestoneClick} labelCount={"N"} - labelClickEvent={() => {}} + labelClickEvent={handleLabelClick} + isMainPage={false} /> {}} /> diff --git a/frontend/src/components/pages/AnotherTest.jsx b/frontend/src/components/pages/AnotherTest.jsx index e7e4b51bd..64805d1d8 100644 --- a/frontend/src/components/pages/AnotherTest.jsx +++ b/frontend/src/components/pages/AnotherTest.jsx @@ -1,8 +1,8 @@ import { useRecoilValue } from "MyRecoil/useRecoilValue"; -import { milestoneAtomState } from "MyRecoil/atom"; +import { milestoneState } from "MyRecoil/atom"; export const AnotherTest = () => { - const milestoneState = useRecoilValue(milestoneAtomState); + const milestoneState = useRecoilValue(milestoneState); const milestoneFilterList = milestoneState.map((filter, i) => (
{filter}
)); diff --git a/frontend/src/components/pages/MainPage.jsx b/frontend/src/components/pages/MainPage.jsx index 471a87418..6e05f7ec8 100644 --- a/frontend/src/components/pages/MainPage.jsx +++ b/frontend/src/components/pages/MainPage.jsx @@ -3,9 +3,7 @@ import styled from "styled-components"; import NewIssue from "./NewIssuePage"; import NoMatch from "./NoMatchPage"; import IssueDetailPage from "./IssueDetailPage"; -// import Labels from "components/Labels/Labels"; import LabelsPage from "./LabelsPage"; -// import Milestones from "components/Milestones/Milestones"; import MilestonesPage from "./MilestonesPage"; import Header from "components/common/Header"; import Navigator from "components/common/Navigator"; diff --git a/frontend/src/components/pages/Test.jsx b/frontend/src/components/pages/Test.jsx index 0222d8adf..b9a7da2d6 100644 --- a/frontend/src/components/pages/Test.jsx +++ b/frontend/src/components/pages/Test.jsx @@ -1,23 +1,22 @@ import { useState } from "react"; import { useRecoilState } from "MyRecoil/useRecoilState"; -import { labelAtomState } from "MyRecoil/atom"; +import { labelState } from "MyRecoil/atom"; import { AnotherTest } from "./AnotherTest"; export const Test = () => { const [labelFilterInput, setLabelFilterInput] = useState(); - const [labelFilterState, setLabelFilterState] = - useRecoilState(labelAtomState); + const [labelFilterState, setLabelFilterState] = useRecoilState(labelState); const labelFilterList = labelFilterState.map((filter, i) => ( {filter} )); - const setLabelFilterInputVal = e => { + const setLabelFilterInputVal = (e) => { setLabelFilterInput(e.target.value); }; const setLabelFilter = () => { - setLabelFilterState(labelFilterState => [ + setLabelFilterState((labelFilterState) => [ ...labelFilterState, labelFilterInput, ]); diff --git a/frontend/src/styles/StyledButtons.jsx b/frontend/src/styles/StyledButtons.jsx index b7fb9330b..ca37db805 100644 --- a/frontend/src/styles/StyledButtons.jsx +++ b/frontend/src/styles/StyledButtons.jsx @@ -2,21 +2,26 @@ import styled from "styled-components"; import Button from "@material-ui/core/Button"; export const TabButton = styled(Button)` - width: ${props => props._width}; + width: ${(props) => props._width}; height: ${({ theme }) => theme.buttonHeights.base}; font-size: ${({ theme }) => theme.fontSizes.xs}; font-weight: bold; color: ${({ theme }) => theme.grayScale.label}; border: 1px solid - ${props => (props._border === "none" ? "none" : props.theme.grayScale.line)}; - border-radius: ${props => + ${(props) => + props._border === "none" ? "none" : props.theme.grayScale.line}; + border-radius: ${(props) => props._radius === "right" ? props.theme.border_radius_mix.right : props._radius === "left" ? props.theme.border_radius_mix.left : props.theme.border_radius_mix.all}; - background-color: ${({ theme }) => - theme.grayScale.background}; //str넣었는데 str넣으라고 오류뜸 + background-color: ${(props) => + props.bgColor && !props.isMainPage + ? props.theme.grayScale.line + : props.theme.grayScale.background}; + /* background-color: ${({ theme }) => + theme.grayScale.background}; //str넣었는데 str넣으라고 오류뜸 */ `; export const AddBtn = styled(Button)` @@ -26,7 +31,6 @@ export const AddBtn = styled(Button)` font-weight: bold; background-color: ${({ theme }) => theme.colors.blue}; color: ${({ theme }) => theme.grayScale.off_white}; - /* border: 1px solid ${({ theme }) => theme.grayScale.label}; */ border-radius: 11px; &:hover { background-color: ${({ theme }) => theme.colors.dark_blue}; @@ -46,7 +50,7 @@ export const StyledLoginButton = styled(Button)` `; export const StyledCancelButton = styled(Button)` - width: ${props => props._width}; + width: ${(props) => props._width}; height: ${({ theme }) => theme.buttonHeights.small}; color: ${({ theme }) => theme.grayScale.label}; font-weight: bold; From 53c15606cbe5a74429107b320ae144589f2d964d Mon Sep 17 00:00:00 2001 From: junzero741 Date: Thu, 17 Jun 2021 22:44:58 +0900 Subject: [PATCH 35/71] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Milestones/MilestoneCard.jsx | 93 ++++++++++++++++--- .../Milestones/MilestonesHeader.jsx | 2 +- frontend/src/util/getPercent.js | 7 ++ 3 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 frontend/src/util/getPercent.js diff --git a/frontend/src/components/Milestones/MilestoneCard.jsx b/frontend/src/components/Milestones/MilestoneCard.jsx index 0ebe39628..3baea1e6f 100644 --- a/frontend/src/components/Milestones/MilestoneCard.jsx +++ b/frontend/src/components/Milestones/MilestoneCard.jsx @@ -1,26 +1,48 @@ import styled from "styled-components"; import { StyledFlexCard } from "styles/StyledCards"; +import { ReactComponent as Milestone } from "images/milestone.svg"; +import { ReactComponent as Archive } from "images/archive.svg"; +import { ReactComponent as Trash } from "images/trash.svg"; +import { ReactComponent as EditIcon } from "images/edit.svg"; const MilestoneCard = () => { return ( -
- 마일스톤 제목 - 완료일 일정 -
-
마일스톤에 대한 설명
+ + + + 마일스톤 제목 + + 완료일 일정 + + 마일스톤에 대한 설명
+ + + + 닫기 + + + + 편집 + + + + 삭제 + +
- 편집 - 삭제 -
-
-
프로그레스바
+ + + -
00%
-
열린 이슈 N 닫힌 이슈 N
+ 00% + + 열린 이슈 N{" "} + 닫힌 이슈 N +
@@ -41,10 +63,12 @@ const Edit = styled.div` display: flex; flex-direction: column; justify-content: space-evenly; + width: 20%; `; const Detail = styled.div` display: flex; + justify-content: space-between; `; const ContentsWrapper = styled.div` @@ -52,3 +76,48 @@ const ContentsWrapper = styled.div` justify-content: space-between; width: 97%; `; + +const EditBlock = styled.div` + display: flex; + justify-content: flex-end; +`; + +const Block = styled.div` + display: flex; + justify-content: space-between; + /* width: 50%; */ +`; + +const IssueCnt = styled.span` + padding: 0 2px; + color: ${({ theme }) => theme.grayScale.label}; + font-size: ${({ theme }) => theme.fontSizes.xs}; +`; + +const Span = styled.span` + padding: 0 ${({ theme }) => theme.fontSizes.xl}; + color: ${({ theme }) => theme.grayScale.label}; + font-size: ${({ theme }) => theme.fontSizes.small}; + align-self: center; +`; + +const GrayFont = styled.div` + color: ${({ theme }) => theme.grayScale.label}; + font-size: ${({ theme }) => theme.fontSizes.small}; +`; + +const ProgressWrapper = styled.div` + display: flex; + justify-content: flex-end; + padding-bottom: ${({ theme }) => theme.fontSizes.xs}; + /* margin-left: 30px; */ +`; + +const EditBtn = styled.div` + padding: 0 ${({ theme }) => theme.fontSizes.xl}; + color: ${({ theme }) => theme.grayScale.label}; + :last-child { + padding-right: 0; + padding-left: ${({ theme }) => theme.fontSizes.xl}; + } +`; diff --git a/frontend/src/components/Milestones/MilestonesHeader.jsx b/frontend/src/components/Milestones/MilestonesHeader.jsx index 3b3e9b001..d8f2234cd 100644 --- a/frontend/src/components/Milestones/MilestonesHeader.jsx +++ b/frontend/src/components/Milestones/MilestonesHeader.jsx @@ -33,7 +33,7 @@ export default MilestonesHeader; const Contents = styled.div` display: flex; justify-content: space-between; - width: 25%; + width: 30%; align-items: center; `; diff --git a/frontend/src/util/getPercent.js b/frontend/src/util/getPercent.js new file mode 100644 index 000000000..53e2799ff --- /dev/null +++ b/frontend/src/util/getPercent.js @@ -0,0 +1,7 @@ +const getPercent = (openCnt, closeCnt) => { + const sum = openCnt + closeCnt; + if (sum === 0) return 0; + return (closeCnt / sum) * 100; +}; + +export default getPercent; From ea08d9f1be9e0434fb0bfbdcdcc25e10e151c424 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Fri, 18 Jun 2021 00:17:50 +0900 Subject: [PATCH 36/71] =?UTF-8?q?style:=20file=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=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=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Issues/IssueList/IssuesHeader.jsx | 6 +++--- .../components/Issues/Menu/MenuFilterBar.jsx | 6 +++--- frontend/src/components/Issues/Menu/MenuTab.jsx | 4 ++-- frontend/src/components/Labels/LabelInput.jsx | 5 +++++ .../src/components/NewIssues/NewIssueForm.jsx | 4 ++-- .../common/{ => Button}/AddButton.jsx | 0 .../common/{ => Button}/ButtonGroup.jsx | 0 .../common/{ => Button}/CancelButton.jsx | 0 .../common/{ => Button}/DropDownButton.jsx | 0 .../common/{ => Button}/SubmitButton.jsx | 0 frontend/src/components/common/FilterModal.jsx | 17 +++++++++-------- frontend/src/components/common/Navigator.jsx | 4 ++-- frontend/src/data.js | 2 +- 13 files changed, 27 insertions(+), 21 deletions(-) rename frontend/src/components/common/{ => Button}/AddButton.jsx (100%) rename frontend/src/components/common/{ => Button}/ButtonGroup.jsx (100%) rename frontend/src/components/common/{ => Button}/CancelButton.jsx (100%) rename frontend/src/components/common/{ => Button}/DropDownButton.jsx (100%) rename frontend/src/components/common/{ => Button}/SubmitButton.jsx (100%) diff --git a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx index a1856ce17..3900d721f 100644 --- a/frontend/src/components/Issues/IssueList/IssuesHeader.jsx +++ b/frontend/src/components/Issues/IssueList/IssuesHeader.jsx @@ -4,7 +4,7 @@ import { ReactComponent as Archive } from "images/archive.svg"; import { ReactComponent as Alert } from "images/alert-circle.svg"; import { ReactComponent as DownArrow } from "images/chevron_down.svg"; import theme from "styles/theme"; -import DropDownButton from "components/common/DropDownButton"; +import DropDownButton from "components/common/Button/DropDownButton"; import FilterModal from "components/common/FilterModal"; import { filter } from "data"; import { StyledGridTitleCard } from "styles/StyledCards"; @@ -35,7 +35,7 @@ const IssuesHeader = ({ //----------중복 코드from MeuFilter -------- const [isFilterClicked, setIsFilterClicked] = useState(false); - const handleClick = useCallback((e) => { + const handleClick = useCallback(e => { isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); @@ -52,7 +52,7 @@ const IssuesHeader = ({ }; }, [isFilterClicked]); - const closeFilterModal = (e) => { + const closeFilterModal = e => { const target = e.target; if ( isFilterClicked && diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index 8462c0194..803dff419 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -1,6 +1,6 @@ import styled from "styled-components"; import { ReactComponent as SearchIcon } from "images/search.svg"; -import DropDownButton from "components/common/DropDownButton"; +import DropDownButton from "components/common/Button/DropDownButton"; import theme from "styles/theme"; import FilterModal from "components/common/FilterModal"; import { useState, useEffect } from "react"; @@ -21,7 +21,7 @@ const MenuFilterBar = () => { }, ""); }; - const handleClick = (e) => { + const handleClick = e => { isFilterClicked === false ? setIsFilterClicked(true) : setIsFilterClicked(false); @@ -35,7 +35,7 @@ const MenuFilterBar = () => { }; }, [isFilterClicked]); - const closeFilterModal = (e) => { + const closeFilterModal = e => { const target = e.target; if (isFilterClicked && !target.closest(".filter-modal")) setIsFilterClicked(false); diff --git a/frontend/src/components/Issues/Menu/MenuTab.jsx b/frontend/src/components/Issues/Menu/MenuTab.jsx index 40abb1d4c..bee8f65a2 100644 --- a/frontend/src/components/Issues/Menu/MenuTab.jsx +++ b/frontend/src/components/Issues/Menu/MenuTab.jsx @@ -1,6 +1,6 @@ import styled from "styled-components"; -import ButtonGroup from "components/common/ButtonGroup"; -import AddButton from "components/common/AddButton"; +import ButtonGroup from "components/common/Button/ButtonGroup"; +import AddButton from "components/common/Button/AddButton"; import { Link } from "react-router-dom"; import { useSetRecoilState } from "recoil"; import { diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index e69de29bb..9354d2a28 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -0,0 +1,5 @@ +const LabelInput = () => { + return
새로운 레이블 추가
; +}; + +export default LabelInput; diff --git a/frontend/src/components/NewIssues/NewIssueForm.jsx b/frontend/src/components/NewIssues/NewIssueForm.jsx index 8240ae742..e0c56d24b 100644 --- a/frontend/src/components/NewIssues/NewIssueForm.jsx +++ b/frontend/src/components/NewIssues/NewIssueForm.jsx @@ -1,8 +1,8 @@ import styled from "styled-components"; import NewIssueInput from "./NewIssueInput"; import IssueCategoryList from "components/common/IssueCategoryList"; -import SubmitButton from "components/common/SubmitButton"; -import CancelButton from "components/common/CancelButton"; +import SubmitButton from "components/common/Button/SubmitButton"; +import CancelButton from "components/common/Button/CancelButton"; const NewIssueForm = () => { return ( diff --git a/frontend/src/components/common/AddButton.jsx b/frontend/src/components/common/Button/AddButton.jsx similarity index 100% rename from frontend/src/components/common/AddButton.jsx rename to frontend/src/components/common/Button/AddButton.jsx diff --git a/frontend/src/components/common/ButtonGroup.jsx b/frontend/src/components/common/Button/ButtonGroup.jsx similarity index 100% rename from frontend/src/components/common/ButtonGroup.jsx rename to frontend/src/components/common/Button/ButtonGroup.jsx diff --git a/frontend/src/components/common/CancelButton.jsx b/frontend/src/components/common/Button/CancelButton.jsx similarity index 100% rename from frontend/src/components/common/CancelButton.jsx rename to frontend/src/components/common/Button/CancelButton.jsx diff --git a/frontend/src/components/common/DropDownButton.jsx b/frontend/src/components/common/Button/DropDownButton.jsx similarity index 100% rename from frontend/src/components/common/DropDownButton.jsx rename to frontend/src/components/common/Button/DropDownButton.jsx diff --git a/frontend/src/components/common/SubmitButton.jsx b/frontend/src/components/common/Button/SubmitButton.jsx similarity index 100% rename from frontend/src/components/common/SubmitButton.jsx rename to frontend/src/components/common/Button/SubmitButton.jsx diff --git a/frontend/src/components/common/FilterModal.jsx b/frontend/src/components/common/FilterModal.jsx index 48c3733ea..62bfcd796 100644 --- a/frontend/src/components/common/FilterModal.jsx +++ b/frontend/src/components/common/FilterModal.jsx @@ -8,23 +8,24 @@ import RadioGroup from "@material-ui/core/RadioGroup"; import FormControlLabel from "@material-ui/core/FormControlLabel"; import FormControl from "@material-ui/core/FormControl"; import FormLabel from "@material-ui/core/FormLabel"; -import { filter } from "data"; +import { filterData } from "data"; import getEngKey from "util/getEngKey"; const FilterModal = () => { const [clickedFilter, setClickedFilterState] = useState(""); const filterType = useRecoilValue(clickedFilterState); - const [filterBarInput, setFilterBarInputState] = - useRecoilState(filterBarInputState); + const [filterBarInput, setFilterBarInputState] = useRecoilState( + filterBarInputState + ); const key = getEngKey(filterType); - const handleChange = (event) => { + const handleChange = event => { setClickedFilterState(event.target.value); setFilterStateByType(event.target.value); }; - const setFilterStateByType = (clickedValue) => { + const setFilterStateByType = clickedValue => { const updatedValue = clickedValue === filterBarInput[getEngKey(filterType)] ? null @@ -72,7 +73,7 @@ const FilterModal = () => { } }; - const filterData = filter[getEngKey(filterType)]; + const filterDataByType = filterData[getEngKey(filterType)]; return ( @@ -86,8 +87,8 @@ const FilterModal = () => { value={clickedFilter} onClick={handleChange} > - {filterData && - filterData.map((text, idx) => ( + {filterDataByType && + filterDataByType.map((text, idx) => ( } diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index 68e4ae99c..c4ffcf048 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -1,6 +1,6 @@ import styled from "styled-components"; -import ButtonGroup from "./ButtonGroup"; -import AddButton from "./AddButton"; +import ButtonGroup from "./Button/ButtonGroup"; +import AddButton from "./Button/AddButton"; import { useSetRecoilState } from "recoil"; import { labelButtonFlagState, diff --git a/frontend/src/data.js b/frontend/src/data.js index b1baf6a04..678529e73 100644 --- a/frontend/src/data.js +++ b/frontend/src/data.js @@ -19,7 +19,7 @@ export const issues = [ }, ]; -export const filter = { +export const filterData = { issue: [ "열린 이슈", "내가 작성한 이슈", From 543c96b9328a6422a39b9dfd2db6e68cf416a1b5 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Fri, 18 Jun 2021 02:53:24 +0900 Subject: [PATCH 37/71] =?UTF-8?q?style:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=9D=B4=EB=A6=84=20svg=20stroke=20=EA=B0=92=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelsHeader.jsx | 10 ---------- frontend/src/components/common/Navigator.jsx | 10 +++++----- frontend/src/images/edit.svg | 4 ++-- frontend/src/images/trash.svg | 8 ++++---- 4 files changed, 11 insertions(+), 21 deletions(-) delete mode 100644 frontend/src/components/Labels/LabelsHeader.jsx diff --git a/frontend/src/components/Labels/LabelsHeader.jsx b/frontend/src/components/Labels/LabelsHeader.jsx deleted file mode 100644 index f05584dea..000000000 --- a/frontend/src/components/Labels/LabelsHeader.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import { StyledGridTitleCard } from "styles/StyledCards"; -const LabelsHeader = () => { - return ( - -
N개의 레이블
-
- ); -}; - -export default LabelsHeader; diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index c4ffcf048..28b506eef 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -20,7 +20,7 @@ const Navigator = () => { }; return ( - + { isMainPage={false} /> {}} /> - + ); }; -export default Navigator; - -const Wrapper = styled.div` +const NavigatorLayout = styled.div` display: flex; justify-content: space-between; `; + +export default Navigator; diff --git a/frontend/src/images/edit.svg b/frontend/src/images/edit.svg index 2f12c0559..5f779e16a 100644 --- a/frontend/src/images/edit.svg +++ b/frontend/src/images/edit.svg @@ -1,4 +1,4 @@ - - + + diff --git a/frontend/src/images/trash.svg b/frontend/src/images/trash.svg index a8c8df7c2..18a6e180a 100644 --- a/frontend/src/images/trash.svg +++ b/frontend/src/images/trash.svg @@ -1,6 +1,6 @@ - - - - + + + + From 09df524c905f248e1591191305ada790e7be684b Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Fri, 18 Jun 2021 02:54:41 +0900 Subject: [PATCH 38/71] =?UTF-8?q?feat:=20Label=20Badge=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/common/LabelBadge.jsx | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 frontend/src/components/common/LabelBadge.jsx diff --git a/frontend/src/components/common/LabelBadge.jsx b/frontend/src/components/common/LabelBadge.jsx new file mode 100644 index 000000000..7c7269124 --- /dev/null +++ b/frontend/src/components/common/LabelBadge.jsx @@ -0,0 +1,23 @@ +import styled from "styled-components"; + +const LabelBadge = ({ text, fontColor, bgColor }) => { + return ( + + {text} + + ); +}; + +const LabelBadgeLayout = styled.div` + position: absolute; + display: flex; + justify-content: center; + align-items: center; + height: ${({ theme }) => theme.buttonHeights.small}; + padding: 0px 16px; + border-radius: 30px; + background: ${props => props.bgColor}; + color: ${props => props.fontColor}; +`; + +export default LabelBadge; From 5af6129db6648190ca849756c5366a784a69e9a9 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Fri, 18 Jun 2021 02:55:40 +0900 Subject: [PATCH 39/71] =?UTF-8?q?style:=20Button=20Group=20=EC=A2=8C?= =?UTF-8?q?=EC=9A=B0=20=EC=9E=90=EB=A6=AC=20=EB=B3=80=EA=B2=BD(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/Button/ButtonGroup.jsx | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/common/Button/ButtonGroup.jsx b/frontend/src/components/common/Button/ButtonGroup.jsx index f3133d9cb..b229bf9b1 100644 --- a/frontend/src/components/common/Button/ButtonGroup.jsx +++ b/frontend/src/components/common/Button/ButtonGroup.jsx @@ -21,38 +21,39 @@ const ButtonGroup = ({ const labelFlag = useRecoilValue(labelButtonFlagState); return ( - - + + theme.buttonWidths.base} _radius={"left"} - bgColor={milestoneFlag} + bgColor={labelFlag} isMainPage={isMainPage} > - - 마일스톤 ({milestoneCount}) + + 레이블 ({labelCount}) - + theme.buttonWidths.base} _radius={"right"} - bgColor={labelFlag} + bgColor={milestoneFlag} isMainPage={isMainPage} > - - 레이블 ({labelCount}) + + 마일스톤 ({milestoneCount}) - + ); }; -const Wrapper = styled.div` +const ButtonGroupLayout = styled.div` display: flex; justify-content: center; + margin-bottom: 24px; `; const ButtonText = styled.div` From c723f7f7c4ede7283a00f316e0db1ae3df524118 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Fri, 18 Jun 2021 02:56:54 +0900 Subject: [PATCH 40/71] =?UTF-8?q?feat:=20Label=20Card=20style=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelCard.jsx | 48 ++++++++++++++++++-- frontend/src/styles/StyledLayout .jsx | 14 ++++++ 2 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 frontend/src/styles/StyledLayout .jsx diff --git a/frontend/src/components/Labels/LabelCard.jsx b/frontend/src/components/Labels/LabelCard.jsx index 821993b97..83fa7a79d 100644 --- a/frontend/src/components/Labels/LabelCard.jsx +++ b/frontend/src/components/Labels/LabelCard.jsx @@ -1,13 +1,51 @@ +import styled from "styled-components"; import { StyledGridCard } from "styles/StyledCards"; +import LabelBadge from "components/common/LabelBadge"; +import { ReactComponent as EditIcon } from "images/edit.svg"; +import { ReactComponent as TrashIcon } from "images/trash.svg"; +import theme from "styles/theme"; +import { CenterJcAi, CenterAi } from "styles/StyledLayout "; const LabelCard = () => { return ( - -
레이블딱지
-
레이블 설명
-
편집 혹은 삭제
-
+ <> + + + + + + + 구디의 모닝 알고리즘 100,000,000일차 ☀️ + + + + + theme.grayScale.label}> + 편집 + + + theme.colors.red}>삭제 + + + ); }; +const LabelDescription = styled.div` + color: ${({ theme }) => theme.grayScale.label}; +`; + +const ButtonText = styled.div` + font-weight: bold; + font-size: ${({ theme }) => theme.fontSizes.xxs}; + color: ${props => props._color}; + padding: 3%; + margin-right: 24px; + cursor: pointer; +`; + export default LabelCard; diff --git a/frontend/src/styles/StyledLayout .jsx b/frontend/src/styles/StyledLayout .jsx new file mode 100644 index 000000000..1d9eac8ca --- /dev/null +++ b/frontend/src/styles/StyledLayout .jsx @@ -0,0 +1,14 @@ +import styled from "styled-components"; + +//컴포넌트 명 수정 예정 + +export const CenterJcAi = styled.div` + display: flex; + justify-content: center; + align-items: center; +`; + +export const CenterAi = styled.div` + display: flex; + align-items: center; +`; From f2b69eef05067e741ec0c2ad6b9de682d5541a82 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Fri, 18 Jun 2021 02:57:44 +0900 Subject: [PATCH 41/71] =?UTF-8?q?feat:=20Label=20Inputs=20style=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelInput.jsx | 60 ++++++++++++++++++- frontend/src/components/Labels/Labels.jsx | 16 ++++- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index 9354d2a28..7b13542e8 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -1,5 +1,63 @@ +import styled from "styled-components"; +import { CenterJcAi } from "styles/StyledLayout "; const LabelInput = () => { - return
새로운 레이블 추가
; + return ( + + 새로운 레이블 추가(Layout 잡는 중) + + 레이블 이름 + + + + 설명(선택) + + + + ); }; +//하드 코딩 된 스타일 값 수정 예정 + +const LabelInputLayout = styled.div` + height: 345px; + border: 1px solid black; + background: #fefefe; + + border: 1px solid #d9dbe9; + box-sizing: border-box; + border-radius: 16px; +`; + +const Title = styled.div` + font-size: ${({ theme }) => theme.fontSizes.xxxl}; + padding: 32px; +`; + +const TextInputContainer = styled(CenterJcAi)` + display: flex; + padding: 0px 24px; + margin-bottom: 16px; + background: #eff0f6; + border-radius: 11px; + width: 904px; + height: 40px; + border: none; + color: ${({ theme }) => theme.grayScale.title_active}; +`; +const SubTitle = styled(CenterJcAi)` + width: 80px; + height: 40px; + font-weight: 500; + font-size: 12px; + line-height: 20px; + color: ${({ theme }) => theme.grayScale.label}; +`; +const TextInput = styled.input` + background: #eff0f6; + width: 100%; + color: ${({ theme }) => theme.grayScale.title_active}; + font-size: 16px; + border: none; +`; + export default LabelInput; diff --git a/frontend/src/components/Labels/Labels.jsx b/frontend/src/components/Labels/Labels.jsx index eaae4385c..35cef0db9 100644 --- a/frontend/src/components/Labels/Labels.jsx +++ b/frontend/src/components/Labels/Labels.jsx @@ -1,11 +1,15 @@ -import LabelsHeader from "./LabelsHeader"; +import styled from "styled-components"; import LabelCard from "./LabelCard"; import LabelInput from "./LabelInput"; - +import { StyledGridTitleCard } from "styles/StyledCards"; +import { CenterAi } from "styles/StyledLayout "; const Labels = () => { return ( <> - + + + N개의 레이블 + @@ -13,4 +17,10 @@ const Labels = () => { ); }; +const HeaderTitle = styled.div` + font-weight: bold; + color: ${({ theme }) => theme.grayScale.label}; + align-items: center; + padding: 0 6%; +`; export default Labels; From 6768258bd24e283a9691b076266ae4281dea8a5d Mon Sep 17 00:00:00 2001 From: junzero741 Date: Fri, 18 Jun 2021 12:23:56 +0900 Subject: [PATCH 42/71] =?UTF-8?q?feat:=20get=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=9B=85=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/hooks/useFetchGet.jsx | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 frontend/src/hooks/useFetchGet.jsx diff --git a/frontend/src/hooks/useFetchGet.jsx b/frontend/src/hooks/useFetchGet.jsx new file mode 100644 index 000000000..506aae17e --- /dev/null +++ b/frontend/src/hooks/useFetchGet.jsx @@ -0,0 +1,31 @@ +import { useState, useEffect } from "react"; + +const useFetchGet = (url) => { + const [data, setData] = useState(); + const [status, setStatus] = useState("대기 중"); + + useEffect(() => { + if (!url) return; + + const fetchData = async () => { + try { + setStatus(`fetch start from ${url}`); + const res = await fetch(url); + if (!res.ok) throw new Error(res.status); + else { + const resData = await res.json(); + setData(resData); + setStatus(`fetch complete from ${url}`); + } + } catch (error) { + setStatus(`fetch failed from ${url} due to ${error}`); + } + }; + + fetchData(); + }, [url]); + + return { status, data }; +}; + +export default useFetchGet; From de989e02c4ecd09d464883f761ed9ff4fa455a36 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Fri, 18 Jun 2021 12:24:18 +0900 Subject: [PATCH 43/71] =?UTF-8?q?WIP:=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=9E=91=EC=97=85?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Milestones/MilestoneCard.jsx | 16 +++-- .../components/Milestones/MilestoneInput.jsx | 63 +++++++++++++++++++ .../src/components/Milestones/Milestones.jsx | 2 + .../src/components/common/CloseButton.jsx | 5 ++ .../src/components/pages/MilestonesPage.jsx | 5 ++ frontend/src/util/getPercent.js | 2 +- 6 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 frontend/src/components/common/CloseButton.jsx diff --git a/frontend/src/components/Milestones/MilestoneCard.jsx b/frontend/src/components/Milestones/MilestoneCard.jsx index 3baea1e6f..53582251f 100644 --- a/frontend/src/components/Milestones/MilestoneCard.jsx +++ b/frontend/src/components/Milestones/MilestoneCard.jsx @@ -4,7 +4,12 @@ import { ReactComponent as Milestone } from "images/milestone.svg"; import { ReactComponent as Archive } from "images/archive.svg"; import { ReactComponent as Trash } from "images/trash.svg"; import { ReactComponent as EditIcon } from "images/edit.svg"; +import getPercent from "util/getPercent"; + const MilestoneCard = () => { + const openedIssueCnt = 1; + const closedIssueCnt = 1; + return ( @@ -35,13 +40,16 @@ const MilestoneCard = () => {
- + - 00% + {getPercent(openedIssueCnt, closedIssueCnt)}% - 열린 이슈 N{" "} - 닫힌 이슈 N + 열린 이슈 {openedIssueCnt}{" "} + 닫힌 이슈 {closedIssueCnt}
diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index e69de29bb..128d3dde9 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -0,0 +1,63 @@ +import styled, { ThemeContext } from "styled-components"; +import AddButton from "components/common/AddButton"; + +const MilestoneInput = () => { + return ( + +
새로운 마일스톤 추가
+ + + + + + + + + + + {}} /> + +
+ ); +}; + +export default MilestoneInput; + +const Header = styled.div` + font-size: ${({ theme }) => theme.fontSizes.xxxl}; +`; + +const CardWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: space-evenly; + height: 288px; + background-color: ${({ theme }) => theme.grayScale.off_white}; + padding: 1%; + border: 1px solid ${({ theme }) => theme.grayScale.line}; + border-radius: ${({ theme }) => theme.border_radius.lg}; +`; + +const BtnWrapper = styled.div` + display: flex; + justify-content: flex-end; +`; + +const InputWrapper = styled.div` + display: flex; + justify-content: space-between; +`; + +const InputHalf = styled.div` + width: 49%; +`; + +const Input = styled.input` + width: 100%; + height: 40px; + background-color: ${({ theme }) => theme.grayScale.input_background}; + border: none; + border-radius: ${({ theme }) => theme.border_radius.base}; + font-size: ${({ theme }) => theme.fontSizes.base}; + padding: 0 ${({ theme }) => theme.paddings.small}; +`; diff --git a/frontend/src/components/Milestones/Milestones.jsx b/frontend/src/components/Milestones/Milestones.jsx index b6edc3d15..ee0c5884c 100644 --- a/frontend/src/components/Milestones/Milestones.jsx +++ b/frontend/src/components/Milestones/Milestones.jsx @@ -1,8 +1,10 @@ import MilestonesHeader from "./MilestonesHeader"; import MilestoneCard from "./MilestoneCard"; +import MilestoneInput from "./MilestoneInput"; const Milestones = () => { return ( <> + diff --git a/frontend/src/components/common/CloseButton.jsx b/frontend/src/components/common/CloseButton.jsx new file mode 100644 index 000000000..5d48a38f7 --- /dev/null +++ b/frontend/src/components/common/CloseButton.jsx @@ -0,0 +1,5 @@ +const CloseButton = () => { + return
; +}; + +export default CloseButton; diff --git a/frontend/src/components/pages/MilestonesPage.jsx b/frontend/src/components/pages/MilestonesPage.jsx index d65e95d0f..62e371321 100644 --- a/frontend/src/components/pages/MilestonesPage.jsx +++ b/frontend/src/components/pages/MilestonesPage.jsx @@ -1,6 +1,11 @@ +import API from "util/API"; import Milestones from "components/Milestones/Milestones"; +import useFetchGet from "hooks/useFetchGet"; const MilestonesPage = () => { + const { status, milestoneData } = useFetchGet(API.milestones()); + // console.log(status, milestoneData); + return ( <> diff --git a/frontend/src/util/getPercent.js b/frontend/src/util/getPercent.js index 53e2799ff..16a0fff18 100644 --- a/frontend/src/util/getPercent.js +++ b/frontend/src/util/getPercent.js @@ -1,7 +1,7 @@ const getPercent = (openCnt, closeCnt) => { const sum = openCnt + closeCnt; if (sum === 0) return 0; - return (closeCnt / sum) * 100; + return Math.floor((closeCnt / sum) * 100); }; export default getPercent; From d5c93d0f3852cc1d19c76e158d82fe05d8e34286 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Fri, 18 Jun 2021 12:39:43 +0900 Subject: [PATCH 44/71] =?UTF-8?q?chore:=20=EC=8A=A4=ED=83=80=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Milestones/MilestoneCard.jsx | 13 +++++++------ .../src/components/Milestones/MilestoneInput.jsx | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/Milestones/MilestoneCard.jsx b/frontend/src/components/Milestones/MilestoneCard.jsx index 53582251f..aad6d2b27 100644 --- a/frontend/src/components/Milestones/MilestoneCard.jsx +++ b/frontend/src/components/Milestones/MilestoneCard.jsx @@ -5,6 +5,7 @@ import { ReactComponent as Archive } from "images/archive.svg"; import { ReactComponent as Trash } from "images/trash.svg"; import { ReactComponent as EditIcon } from "images/edit.svg"; import getPercent from "util/getPercent"; +import theme from "styles/theme"; const MilestoneCard = () => { const openedIssueCnt = 1; @@ -25,16 +26,16 @@ const MilestoneCard = () => { - + theme.grayScale.label}> 닫기 - - + theme.grayScale.label}> + 편집 - - + theme.colors.red}> + 삭제 @@ -123,7 +124,7 @@ const ProgressWrapper = styled.div` const EditBtn = styled.div` padding: 0 ${({ theme }) => theme.fontSizes.xl}; - color: ${({ theme }) => theme.grayScale.label}; + color: ${(props) => props._color}; :last-child { padding-right: 0; padding-left: ${({ theme }) => theme.fontSizes.xl}; diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index 128d3dde9..70ae4c1f4 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -1,5 +1,5 @@ import styled, { ThemeContext } from "styled-components"; -import AddButton from "components/common/AddButton"; +import AddButton from "components/common/Button/AddButton"; const MilestoneInput = () => { return ( From 04d4b6b7b1b447de84022a1da5bfeb613712bed1 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Sat, 19 Jun 2021 16:17:44 +0900 Subject: [PATCH 45/71] =?UTF-8?q?feat:=20useFecth=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=ED=9B=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/pages/MilestonesPage.jsx | 9 ++++-- frontend/src/hooks/useFetchGet.jsx | 29 ++++++++++++++----- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/pages/MilestonesPage.jsx b/frontend/src/components/pages/MilestonesPage.jsx index 62e371321..5983a16cd 100644 --- a/frontend/src/components/pages/MilestonesPage.jsx +++ b/frontend/src/components/pages/MilestonesPage.jsx @@ -1,10 +1,13 @@ +import { useState } from "react"; import API from "util/API"; import Milestones from "components/Milestones/Milestones"; -import useFetchGet from "hooks/useFetchGet"; +import useFetch from "hooks/useFetchGet"; const MilestonesPage = () => { - const { status, milestoneData } = useFetchGet(API.milestones()); - // console.log(status, milestoneData); + const [milestoneData, setMilestoneData] = useState(); + const status = useFetch(API.milestones(), "GET", setMilestoneData); + + console.log(milestoneData, status); return ( <> diff --git a/frontend/src/hooks/useFetchGet.jsx b/frontend/src/hooks/useFetchGet.jsx index 506aae17e..e2b12397c 100644 --- a/frontend/src/hooks/useFetchGet.jsx +++ b/frontend/src/hooks/useFetchGet.jsx @@ -1,20 +1,36 @@ import { useState, useEffect } from "react"; -const useFetchGet = (url) => { - const [data, setData] = useState(); +const useFetch = (url, method, callback, reqData = null) => { const [status, setStatus] = useState("대기 중"); + const fetchContent = + method === "GET" + ? { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + }, + } + : { + method: method, + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + }, + body: JSON.stringify(reqData), + }; + useEffect(() => { if (!url) return; const fetchData = async () => { try { setStatus(`fetch start from ${url}`); - const res = await fetch(url); + const res = await fetch(url, fetchContent); if (!res.ok) throw new Error(res.status); else { const resData = await res.json(); - setData(resData); + callback(resData); setStatus(`fetch complete from ${url}`); } } catch (error) { @@ -24,8 +40,7 @@ const useFetchGet = (url) => { fetchData(); }, [url]); - - return { status, data }; + return status; }; -export default useFetchGet; +export default useFetch; From 856fd2b1191760026257da669a3c671968b2ce72 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Sat, 19 Jun 2021 22:15:13 +0900 Subject: [PATCH 46/71] =?UTF-8?q?feat:=20Labels=20Style=20=EC=99=84?= =?UTF-8?q?=EC=84=B1(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelInput.jsx | 196 +++++++++++++++--- frontend/src/components/Labels/Labels.jsx | 3 +- frontend/src/data.js | 16 ++ frontend/src/images/x-square.svg | 2 +- frontend/src/styles/StyledLayout .jsx | 4 +- frontend/src/styles/theme.js | 1 + 6 files changed, 191 insertions(+), 31 deletions(-) diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index 7b13542e8..1de05ec62 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -1,50 +1,180 @@ import styled from "styled-components"; -import { CenterJcAi } from "styles/StyledLayout "; -const LabelInput = () => { +import { DisplayFlex, CenterAi, CenterJcAi } from "styles/StyledLayout "; +import { ReactComponent as RefreshIcon } from "images/refresh-ccw.svg"; +import { ReactComponent as XIcon } from "images/x-square.svg"; +import { ReactComponent as EditIcon } from "images/edit.svg"; +import { ReactComponent as PlusIcon } from "images/plus.svg"; +import { useState } from "react"; +import LabelBadge from "components/common/LabelBadge"; +import theme from "styles/theme"; +import { labelData } from "data"; +const LabelInput = ({ isEditor }) => { + const [inputValue, setInputValue] = useState(false); + const { + creatorTitle, + editorTitle, + inputTitles, + bgColorTitles, + textColorTitles, + buttons, + } = labelData; + const handleClickRadioButton = event => { + const value = event.target.value; + setInputValue(value); + }; + + const changeColor = () => {}; + return ( - - 새로운 레이블 추가(Layout 잡는 중) - - 레이블 이름 - - - - 설명(선택) - - + + {isEditor ? editorTitle : creatorTitle} + + + + + + + {inputTitles.map(title => ( + + {title} + + + ))} + + + {bgColorTitles} + + + + + {textColorTitles} + + {buttons.radio.map((button, idx) => { + return ( + <> + + {button.text} + + ); + })} + + + + + {isEditor && ( + + + {buttons.cancel} + + )} + + {isEditor ? ( + + ) : ( + + )} + {buttons.submit} + + + + ); }; -//하드 코딩 된 스타일 값 수정 예정 - const LabelInputLayout = styled.div` height: 345px; - border: 1px solid black; - background: #fefefe; + background-color: ${({ theme }) => theme.grayScale.off_white}; + border: 1px solid ${({ theme }) => theme.grayScale.line}; + border-radius: ${props => (props.isEditor ? "none" : "16px")}; + margin-bottom: ${props => (props.isEditor ? 0 : "2%")}; +`; - border: 1px solid #d9dbe9; - box-sizing: border-box; - border-radius: 16px; +const MainLayout = styled.div` + display: flex; + position: relative; `; -const Title = styled.div` - font-size: ${({ theme }) => theme.fontSizes.xxxl}; - padding: 32px; +const ButtonContainer = styled.div` + display: flex; + justify-content: flex-end; `; -const TextInputContainer = styled(CenterJcAi)` +const PreviewContainer = styled.div` + width: 20%; + display: flex; + justify-content: center; + align-items: center; +`; + +const SettingContainer = styled.div` + width: 80%; + padding: 0 50px; +`; + +const TextInputContainer = styled(CenterAi)` display: flex; padding: 0px 24px; + margin-right: 1%; margin-bottom: 16px; - background: #eff0f6; + background: ${({ theme }) => theme.grayScale.input_background}; border-radius: 11px; - width: 904px; + width: ${props => props._width}; height: 40px; border: none; color: ${({ theme }) => theme.grayScale.title_active}; `; -const SubTitle = styled(CenterJcAi)` + +const CancelButton = styled.div` + display: flex; + justify-content: center; + align-items: center; + padding: 0px 16px; + margin: 0 3px; + width: 120px; + height: 40px; + color: ${theme.colors.blue}; + background: ${theme.colors.off_white}; + border: 2px solid ${theme.colors.blue}; + border-radius: 11px; + cursor: pointer; +`; + +const SubmitButton = styled.div` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 0px 16px; + margin: 0 3px; + width: 120px; + height: 40px; + background: ${theme.colors.blue}; + color: ${theme.grayScale.off_white}; + border-radius: 11px; + cursor: pointer; +`; + +const RadioButton = styled.input` + cursor: pointer; +`; + +const Title = styled.div` + font-size: ${({ theme }) => theme.fontSizes.xxxl}; + padding: 32px; +`; + +const SubTitle = styled(CenterAi)` width: 80px; height: 40px; font-weight: 500; @@ -52,12 +182,22 @@ const SubTitle = styled(CenterJcAi)` line-height: 20px; color: ${({ theme }) => theme.grayScale.label}; `; + const TextInput = styled.input` - background: #eff0f6; + background: ${({ theme }) => theme.grayScale.input_background}; width: 100%; color: ${({ theme }) => theme.grayScale.title_active}; - font-size: 16px; border: none; `; +const RadioText = styled.div` + color: ${({ theme }) => theme.grayScale.body}; + font-size: ${({ theme }) => theme.fontSizes.xs}; + line-height: 28px; + padding: 0; +`; + +const Icon = styled(RefreshIcon)` + cursor: pointer; +`; export default LabelInput; diff --git a/frontend/src/components/Labels/Labels.jsx b/frontend/src/components/Labels/Labels.jsx index 35cef0db9..b942b3922 100644 --- a/frontend/src/components/Labels/Labels.jsx +++ b/frontend/src/components/Labels/Labels.jsx @@ -6,11 +6,12 @@ import { CenterAi } from "styles/StyledLayout "; const Labels = () => { return ( <> - + N개의 레이블 + diff --git a/frontend/src/data.js b/frontend/src/data.js index 678529e73..3c379e752 100644 --- a/frontend/src/data.js +++ b/frontend/src/data.js @@ -33,3 +33,19 @@ export const filterData = { author: ["daisy", "goody"], openClose: ["선택된 이슈 열기", "선택된 이슈 닫기"], }; + +export const labelData = { + creatorTitle: "새로운 레이블 추가", + editorTitle: "레이블 편집", + inputTitles: ["레이블 이름", "설명(선택)"], + bgColorTitles: "배경 색상", + textColorTitles: "텍스트 색상", + buttons: { + cancel: "취소", + submit: "완료", + radio: [ + { value: "light", text: "밝은 색" }, + { value: "dark", text: "어두운 색" }, + ], + }, +}; diff --git a/frontend/src/images/x-square.svg b/frontend/src/images/x-square.svg index 84c619a25..60a7d64bf 100644 --- a/frontend/src/images/x-square.svg +++ b/frontend/src/images/x-square.svg @@ -1,3 +1,3 @@ - + diff --git a/frontend/src/styles/StyledLayout .jsx b/frontend/src/styles/StyledLayout .jsx index 1d9eac8ca..6941a20e0 100644 --- a/frontend/src/styles/StyledLayout .jsx +++ b/frontend/src/styles/StyledLayout .jsx @@ -1,7 +1,9 @@ import styled from "styled-components"; //컴포넌트 명 수정 예정 - +export const DisplayFlex = styled.div` + display: flex; +`; export const CenterJcAi = styled.div` display: flex; justify-content: center; diff --git a/frontend/src/styles/theme.js b/frontend/src/styles/theme.js index a3a9cf433..656f9d8dd 100644 --- a/frontend/src/styles/theme.js +++ b/frontend/src/styles/theme.js @@ -20,6 +20,7 @@ const buttonHeights = { }; const fontSizes = { + xxs: calcRem(12), xs: calcRem(13), small: calcRem(14), base: calcRem(16), From f3d44c138bd677f80e0c9ed6b612e1b0596be0c5 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Sun, 20 Jun 2021 20:02:41 +0900 Subject: [PATCH 47/71] =?UTF-8?q?WIP:=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4=20=ED=8E=98=EC=9D=B4=EC=A7=80=20fetch=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 5 ++ .../components/Milestones/MilestoneCard.jsx | 26 ++++----- .../components/Milestones/MilestoneInput.jsx | 55 +++++++++++++++++-- .../src/components/Milestones/Milestones.jsx | 33 +++++++++-- frontend/src/components/common/Navigator.jsx | 20 +++++-- .../src/components/pages/MilestonesPage.jsx | 15 +---- frontend/src/hooks/useFetch.jsx | 51 +++++++++++++++++ frontend/src/hooks/useFetchGet.jsx | 46 ---------------- 8 files changed, 164 insertions(+), 87 deletions(-) create mode 100644 frontend/src/hooks/useFetch.jsx delete mode 100644 frontend/src/hooks/useFetchGet.jsx diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 1cf540463..79b138464 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -31,3 +31,8 @@ export const milestoneButtonFlagState = atom({ key: "milestoneButtonFlag", default: false, }); + +export const milestoneAddButtonFlagState = atom({ + key: "milestoneAddButtonFlagState", + default: false, +}); diff --git a/frontend/src/components/Milestones/MilestoneCard.jsx b/frontend/src/components/Milestones/MilestoneCard.jsx index aad6d2b27..9b6af0b18 100644 --- a/frontend/src/components/Milestones/MilestoneCard.jsx +++ b/frontend/src/components/Milestones/MilestoneCard.jsx @@ -7,9 +7,8 @@ import { ReactComponent as EditIcon } from "images/edit.svg"; import getPercent from "util/getPercent"; import theme from "styles/theme"; -const MilestoneCard = () => { - const openedIssueCnt = 1; - const closedIssueCnt = 1; +const MilestoneCard = ({ data }) => { + const { id, title, description, dueDate, openIssues, closedIssues } = data; return ( @@ -18,11 +17,11 @@ const MilestoneCard = () => { - 마일스톤 제목 + {title} - 완료일 일정 + {dueDate} - 마일스톤에 대한 설명 + {description} @@ -41,16 +40,13 @@ const MilestoneCard = () => {
- + - {getPercent(openedIssueCnt, closedIssueCnt)}% + {getPercent(openIssues, closedIssues)}% - 열린 이슈 {openedIssueCnt}{" "} - 닫힌 이슈 {closedIssueCnt} + 열린 이슈 {openIssues}{" "} + 닫힌 이슈 {closedIssues}
@@ -72,11 +68,13 @@ const Edit = styled.div` display: flex; flex-direction: column; justify-content: space-evenly; + align-items: flex-end; width: 20%; `; const Detail = styled.div` display: flex; + flex-direction: row; justify-content: space-between; `; @@ -124,7 +122,7 @@ const ProgressWrapper = styled.div` const EditBtn = styled.div` padding: 0 ${({ theme }) => theme.fontSizes.xl}; - color: ${(props) => props._color}; + color: ${props => props._color}; :last-child { padding-right: 0; padding-left: ${({ theme }) => theme.fontSizes.xl}; diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index 70ae4c1f4..c88959afb 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -1,21 +1,66 @@ -import styled, { ThemeContext } from "styled-components"; +import styled from "styled-components"; +import { useState, useCallback } from "react"; import AddButton from "components/common/Button/AddButton"; +import useFetch from "hooks/useFetch"; +import API from "util/API"; const MilestoneInput = () => { + const [inputData, setInputData] = useState({}); + const [milestoneData, setMilestoneData] = useState(); + const { res, fetchData } = useFetch( + API.milestones(), + "POST", + setMilestoneData, + inputData + ); + + const handleTitleChange = e => { + setInputData({ + ...inputData, + title: e.target.value, + }); + }; + + const handleDateChange = e => { + setInputData({ + ...inputData, + dueDate: e.target.value, + }); + }; + + const handleDescChange = e => { + setInputData({ + ...inputData, + description: e.target.value, + }); + }; + + const handleSubmit = () => { + fetchData(); + }; + return (
새로운 마일스톤 추가
- + - + - + - {}} /> +
); diff --git a/frontend/src/components/Milestones/Milestones.jsx b/frontend/src/components/Milestones/Milestones.jsx index ee0c5884c..0c999096a 100644 --- a/frontend/src/components/Milestones/Milestones.jsx +++ b/frontend/src/components/Milestones/Milestones.jsx @@ -1,14 +1,37 @@ +import { useState, useEffect } from "react"; import MilestonesHeader from "./MilestonesHeader"; import MilestoneCard from "./MilestoneCard"; import MilestoneInput from "./MilestoneInput"; +import { milestoneAddButtonFlagState } from "RecoilStore/Atoms"; +import { useRecoilValue } from "recoil"; +import useFetch from "hooks/useFetch"; +import API from "util/API"; + const Milestones = () => { + const milestoneAddBtn = useRecoilValue(milestoneAddButtonFlagState); + const [milestone, setMilestone] = useState(); + const { status, fetchData, data } = useFetch(API.milestones(), "GET"); + const { res, st } = fetchData(); + setMilestone(res); + + console.log("in component: ", res, st); + console.log("in component: ", data, status, milestone); + + const milestoneList = data.milestones.map((milestone, i) => ( + + )); + return ( <> - - - - - + {milestoneAddBtn ? ( + <> + + + + ) : ( + <> + )} + {data && milestoneList} ); }; diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index 28b506eef..24f7453f7 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -1,15 +1,22 @@ import styled from "styled-components"; import ButtonGroup from "./Button/ButtonGroup"; import AddButton from "./Button/AddButton"; -import { useSetRecoilState } from "recoil"; +import { useRecoilState } from "recoil"; import { labelButtonFlagState, milestoneButtonFlagState, + milestoneAddButtonFlagState, } from "RecoilStore/Atoms"; const Navigator = () => { - const setMilestoneFlag = useSetRecoilState(milestoneButtonFlagState); - const setLabelFlag = useSetRecoilState(labelButtonFlagState); + const [milestoneFlag, setMilestoneFlag] = useRecoilState( + milestoneButtonFlagState + ); + const [labelFlag, setLabelFlag] = useRecoilState(labelButtonFlagState); + const [milestoneAddBtnFlag, setMilestoneAddBtnFlag] = useRecoilState( + milestoneAddButtonFlagState + ); + const handleMilestoneClick = () => { setMilestoneFlag(true); setLabelFlag(false); @@ -19,6 +26,11 @@ const Navigator = () => { setLabelFlag(true); }; + const handelAddClick = () => { + if (milestoneFlag) setMilestoneAddBtnFlag(!milestoneAddBtnFlag); + else if (!milestoneFlag) setMilestoneAddBtnFlag(false); + }; + return ( { labelClickEvent={handleLabelClick} isMainPage={false} /> - {}} /> + ); }; diff --git a/frontend/src/components/pages/MilestonesPage.jsx b/frontend/src/components/pages/MilestonesPage.jsx index 5983a16cd..a1834fc0e 100644 --- a/frontend/src/components/pages/MilestonesPage.jsx +++ b/frontend/src/components/pages/MilestonesPage.jsx @@ -1,19 +1,8 @@ -import { useState } from "react"; -import API from "util/API"; +import { useState, useEffect } from "react"; import Milestones from "components/Milestones/Milestones"; -import useFetch from "hooks/useFetchGet"; const MilestonesPage = () => { - const [milestoneData, setMilestoneData] = useState(); - const status = useFetch(API.milestones(), "GET", setMilestoneData); - - console.log(milestoneData, status); - - return ( - <> - - - ); + return <>{}; }; export default MilestonesPage; diff --git a/frontend/src/hooks/useFetch.jsx b/frontend/src/hooks/useFetch.jsx new file mode 100644 index 000000000..13d9e6eb3 --- /dev/null +++ b/frontend/src/hooks/useFetch.jsx @@ -0,0 +1,51 @@ +import { useState, useEffect } from "react"; + +const useFetch = (url, method, reqData = null) => { + const [data, setData] = useState(); + const [status, setStatus] = useState("대기 중"); + console.log("useFetch initiated"); + + const fetchContent = + method === "GET" + ? { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + }, + } + : { + method: method, + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + }, + body: JSON.stringify(reqData), + }; + + const fetchData = async () => { + console.log("fetchData func initiated"); + try { + setStatus(`fetch start from ${url}`); + const res = await fetch(url, fetchContent); + if (!res.ok) throw new Error(res.status); + else { + const resData = await res.json(); + console.log("in useFetch:", resData); + setData(resData); + setStatus(`fetch complete from ${url}`); + return { resData, status }; + } + } catch (error) { + setStatus(`fetch failed from ${url} due to ${error}`); + } + }; + + useEffect(() => { + fetchData(); + }, []); + + // fetchData(); + return { status, fetchData, data }; +}; + +export default useFetch; diff --git a/frontend/src/hooks/useFetchGet.jsx b/frontend/src/hooks/useFetchGet.jsx deleted file mode 100644 index e2b12397c..000000000 --- a/frontend/src/hooks/useFetchGet.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import { useState, useEffect } from "react"; - -const useFetch = (url, method, callback, reqData = null) => { - const [status, setStatus] = useState("대기 중"); - - const fetchContent = - method === "GET" - ? { - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("accessToken")}`, - }, - } - : { - method: method, - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${localStorage.getItem("accessToken")}`, - }, - body: JSON.stringify(reqData), - }; - - useEffect(() => { - if (!url) return; - - const fetchData = async () => { - try { - setStatus(`fetch start from ${url}`); - const res = await fetch(url, fetchContent); - if (!res.ok) throw new Error(res.status); - else { - const resData = await res.json(); - callback(resData); - setStatus(`fetch complete from ${url}`); - } - } catch (error) { - setStatus(`fetch failed from ${url} due to ${error}`); - } - }; - - fetchData(); - }, [url]); - return status; -}; - -export default useFetch; From 223d3b55c7f92ede324a2515bdb12b85d2a5041a Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Sun, 20 Jun 2021 20:05:44 +0900 Subject: [PATCH 48/71] =?UTF-8?q?WIP:=20Label=20page=20=EC=83=9D=EC=84=B1(?= =?UTF-8?q?#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelInput.jsx | 67 +++++++++++++++---- frontend/src/components/Labels/Labels.jsx | 9 ++- .../src/components/pages/MilestonesPage.jsx | 2 +- frontend/src/hooks/useDebounce.jsx | 14 ++++ .../hooks/{useFetchGet.jsx => useFetch.jsx} | 1 + 5 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 frontend/src/hooks/useDebounce.jsx rename frontend/src/hooks/{useFetchGet.jsx => useFetch.jsx} (99%) diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index 1de05ec62..bd9eccf9a 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -4,12 +4,26 @@ import { ReactComponent as RefreshIcon } from "images/refresh-ccw.svg"; import { ReactComponent as XIcon } from "images/x-square.svg"; import { ReactComponent as EditIcon } from "images/edit.svg"; import { ReactComponent as PlusIcon } from "images/plus.svg"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import LabelBadge from "components/common/LabelBadge"; import theme from "styles/theme"; import { labelData } from "data"; +import useDebounce from "hooks/useDebounce"; const LabelInput = ({ isEditor }) => { - const [inputValue, setInputValue] = useState(false); + //🔥아래 상태 한번에 관리할까 말까 고민중⭐️ + const initLabelState = { + name: null, + description: null, + bgColor: null, + textColor: null, + }; + const [input, setInput] = useState(""); + const [textColor, setTextColor] = useState(false); + const [backGroundColor, setBackGroundColor] = useState( + theme.grayScale.input_background + ); + const [labelName, setLabelName] = useState("레이블 이름"); + const [labelDescription, setLabelDescription] = useState(""); const { creatorTitle, editorTitle, @@ -18,12 +32,35 @@ const LabelInput = ({ isEditor }) => { textColorTitles, buttons, } = labelData; + console.log(textColor); + const handleClickRadioButton = event => { const value = event.target.value; - setInputValue(value); + setTextColor(value); }; - const changeColor = () => {}; + const test = useDebounce(input, 1000); //커스텀 훅은 컴포넌트 안에서 호출되어야 하는 부분 고려! + console.log(test); + console.log(backGroundColor); + const handleTypingName = event => { + if (event.target.id === "0") { + const textInput = event.target.value; + setLabelName(textInput); + } else { + //🔥description 해결중 : 작성 후 1초 뒤에 set되면서 리렌더링 되도록 하고 싶음(디바운스) + setInput(event.target.value); + setLabelDescription(input); + } + }; + const getFontColor = () => { + return textColor === "light" + ? theme.grayScale.off_white + : theme.grayScale.black; + }; + const changeColor = () => { + const randomColor = Math.floor(Math.random() * 16777215).toString(16); + setBackGroundColor(`#${randomColor}`); + }; return ( @@ -31,23 +68,27 @@ const LabelInput = ({ isEditor }) => { - {inputTitles.map(title => ( - + {inputTitles.map((title, idx) => ( + {title} - + ))} {bgColorTitles} - + @@ -59,7 +100,7 @@ const LabelInput = ({ isEditor }) => { @@ -186,6 +227,8 @@ const SubTitle = styled(CenterAi)` const TextInput = styled.input` background: ${({ theme }) => theme.grayScale.input_background}; width: 100%; + height: 100%; + color: ${({ theme }) => theme.grayScale.title_active}; border: none; `; diff --git a/frontend/src/components/Labels/Labels.jsx b/frontend/src/components/Labels/Labels.jsx index b942b3922..9da147f2e 100644 --- a/frontend/src/components/Labels/Labels.jsx +++ b/frontend/src/components/Labels/Labels.jsx @@ -2,8 +2,15 @@ import styled from "styled-components"; import LabelCard from "./LabelCard"; import LabelInput from "./LabelInput"; import { StyledGridTitleCard } from "styles/StyledCards"; -import { CenterAi } from "styles/StyledLayout "; +import useFetch from "hooks/useFetch"; +import { useState } from "react"; +import API from "util/API"; + const Labels = () => { + const [LabelData, setLabelData] = useState(); + const status = useFetch(API.labels(), "GET", setLabelData); + console.log(LabelData, "status", status); + return ( <> diff --git a/frontend/src/components/pages/MilestonesPage.jsx b/frontend/src/components/pages/MilestonesPage.jsx index 5983a16cd..b12abec49 100644 --- a/frontend/src/components/pages/MilestonesPage.jsx +++ b/frontend/src/components/pages/MilestonesPage.jsx @@ -1,7 +1,7 @@ import { useState } from "react"; import API from "util/API"; import Milestones from "components/Milestones/Milestones"; -import useFetch from "hooks/useFetchGet"; +import useFetch from "hooks/useFetch"; const MilestonesPage = () => { const [milestoneData, setMilestoneData] = useState(); diff --git a/frontend/src/hooks/useDebounce.jsx b/frontend/src/hooks/useDebounce.jsx new file mode 100644 index 000000000..89542fdd6 --- /dev/null +++ b/frontend/src/hooks/useDebounce.jsx @@ -0,0 +1,14 @@ +import { useState, useEffect } from "react"; +const useDebounce = (value, timeout) => { + const [state, setState] = useState(value); + + useEffect(() => { + const handler = setTimeout(() => setState(value), timeout); + + return () => clearTimeout(handler); + }, [value, timeout]); + + return state; +}; + +export default useDebounce; diff --git a/frontend/src/hooks/useFetchGet.jsx b/frontend/src/hooks/useFetch.jsx similarity index 99% rename from frontend/src/hooks/useFetchGet.jsx rename to frontend/src/hooks/useFetch.jsx index e2b12397c..7c245cc50 100644 --- a/frontend/src/hooks/useFetchGet.jsx +++ b/frontend/src/hooks/useFetch.jsx @@ -1,6 +1,7 @@ import { useState, useEffect } from "react"; const useFetch = (url, method, callback, reqData = null) => { + ""; const [status, setStatus] = useState("대기 중"); const fetchContent = From 0d12b2d0fc29c2d2c2925e0cc76382cbb43d47f6 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Sun, 20 Jun 2021 20:56:15 +0900 Subject: [PATCH 49/71] =?UTF-8?q?feat:=20fetchData=20=EC=9C=A0=ED=8B=B8?= =?UTF-8?q?=ED=95=A8=EC=88=98=EB=A1=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Milestones/Milestones.jsx | 22 ++++++++----- frontend/src/hooks/useFetch.jsx | 17 +++++----- frontend/src/util/fetchData.js | 33 +++++++++++++++++++ 3 files changed, 55 insertions(+), 17 deletions(-) create mode 100644 frontend/src/util/fetchData.js diff --git a/frontend/src/components/Milestones/Milestones.jsx b/frontend/src/components/Milestones/Milestones.jsx index 0c999096a..d5d475560 100644 --- a/frontend/src/components/Milestones/Milestones.jsx +++ b/frontend/src/components/Milestones/Milestones.jsx @@ -6,20 +6,21 @@ import { milestoneAddButtonFlagState } from "RecoilStore/Atoms"; import { useRecoilValue } from "recoil"; import useFetch from "hooks/useFetch"; import API from "util/API"; +import fetchData from "util/fetchData"; const Milestones = () => { const milestoneAddBtn = useRecoilValue(milestoneAddButtonFlagState); const [milestone, setMilestone] = useState(); - const { status, fetchData, data } = useFetch(API.milestones(), "GET"); - const { res, st } = fetchData(); - setMilestone(res); - console.log("in component: ", res, st); - console.log("in component: ", data, status, milestone); + const fetchMilestones = async () => { + const { milestones } = await fetchData(API.milestones(), "GET"); + console.log(milestones); + setMilestone(milestones); + }; - const milestoneList = data.milestones.map((milestone, i) => ( - - )); + useEffect(() => { + fetchMilestones(); + }, []); return ( <> @@ -31,7 +32,10 @@ const Milestones = () => { ) : ( <> )} - {data && milestoneList} + {milestone && + milestone.map((milestone, i) => ( + + ))} ); }; diff --git a/frontend/src/hooks/useFetch.jsx b/frontend/src/hooks/useFetch.jsx index 13d9e6eb3..2bc1c64f8 100644 --- a/frontend/src/hooks/useFetch.jsx +++ b/frontend/src/hooks/useFetch.jsx @@ -1,11 +1,12 @@ import { useState, useEffect } from "react"; +import fetchData from "util/fetchData"; -const useFetch = (url, method, reqData = null) => { - const [data, setData] = useState(); +const useFetch = (url, method, callback, reqData = null) => { const [status, setStatus] = useState("대기 중"); + const [error, setError] = useState(null); console.log("useFetch initiated"); - const fetchContent = + const option = method === "GET" ? { headers: { @@ -26,17 +27,18 @@ const useFetch = (url, method, reqData = null) => { console.log("fetchData func initiated"); try { setStatus(`fetch start from ${url}`); - const res = await fetch(url, fetchContent); + const res = await fetch(url, option); + const resData = await res.json(); if (!res.ok) throw new Error(res.status); else { - const resData = await res.json(); console.log("in useFetch:", resData); - setData(resData); + callback(resData); setStatus(`fetch complete from ${url}`); return { resData, status }; } } catch (error) { setStatus(`fetch failed from ${url} due to ${error}`); + setError(error); } }; @@ -44,8 +46,7 @@ const useFetch = (url, method, reqData = null) => { fetchData(); }, []); - // fetchData(); - return { status, fetchData, data }; + return { status, fetchData }; }; export default useFetch; diff --git a/frontend/src/util/fetchData.js b/frontend/src/util/fetchData.js new file mode 100644 index 000000000..bda5a767a --- /dev/null +++ b/frontend/src/util/fetchData.js @@ -0,0 +1,33 @@ +const fetchData = async (url, method, reqData) => { + const option = + method === "GET" + ? { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + }, + } + : { + method: method, + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + }, + body: JSON.stringify(reqData), + }; + + console.log("fetchData func initiated"); + try { + const res = await fetch(url, option); + const resData = await res.json(); + if (!res.ok) throw new Error(res.status); + else { + console.log("in useFetch:", resData); + return resData; + } + } catch (error) { + console.error("error occured"); + } +}; + +export default fetchData; From c514139ff50983fe7bad33fab7028a8a381b49ea Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Sun, 20 Jun 2021 21:23:25 +0900 Subject: [PATCH 50/71] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4=20=EC=B6=94=EA=B0=80=EC=99=80=20=EC=83=88=EB=A1=9C?= =?UTF-8?q?=EA=B3=A0=EC=B9=A8=20=EC=97=86=EC=9D=B4=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Milestones/MilestoneInput.jsx | 6 ++++++ frontend/src/components/Milestones/Milestones.jsx | 9 ++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index c88959afb..f905ec2c8 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -3,10 +3,15 @@ import { useState, useCallback } from "react"; import AddButton from "components/common/Button/AddButton"; import useFetch from "hooks/useFetch"; import API from "util/API"; +import { useSetRecoilState } from "recoil"; +import { milestoneAddButtonFlagState } from "RecoilStore/Atoms"; const MilestoneInput = () => { const [inputData, setInputData] = useState({}); const [milestoneData, setMilestoneData] = useState(); + const setMilestoneAddButtonFlag = useSetRecoilState( + milestoneAddButtonFlagState + ); const { res, fetchData } = useFetch( API.milestones(), "POST", @@ -37,6 +42,7 @@ const MilestoneInput = () => { const handleSubmit = () => { fetchData(); + setMilestoneAddButtonFlag(false); }; return ( diff --git a/frontend/src/components/Milestones/Milestones.jsx b/frontend/src/components/Milestones/Milestones.jsx index d5d475560..74de77543 100644 --- a/frontend/src/components/Milestones/Milestones.jsx +++ b/frontend/src/components/Milestones/Milestones.jsx @@ -4,7 +4,6 @@ import MilestoneCard from "./MilestoneCard"; import MilestoneInput from "./MilestoneInput"; import { milestoneAddButtonFlagState } from "RecoilStore/Atoms"; import { useRecoilValue } from "recoil"; -import useFetch from "hooks/useFetch"; import API from "util/API"; import fetchData from "util/fetchData"; @@ -20,7 +19,7 @@ const Milestones = () => { useEffect(() => { fetchMilestones(); - }, []); + }, [milestoneAddBtn]); return ( <> @@ -33,9 +32,9 @@ const Milestones = () => { <> )} {milestone && - milestone.map((milestone, i) => ( - - ))} + milestone + .map((milestone, i) => ) + .reverse()} ); }; From 92ce6a03ce0d917eacb92395ff48809aa823d774 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Sun, 20 Jun 2021 22:58:20 +0900 Subject: [PATCH 51/71] =?UTF-8?q?feat:=20fetchData=20=EC=9C=A0=ED=8B=B8?= =?UTF-8?q?=ED=95=A8=EC=88=98=EB=A1=9C=20=EC=B6=94=EA=B0=80,=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 5 ++ .../components/Milestones/MilestoneCard.jsx | 47 +++++++++++++++++-- .../components/Milestones/MilestoneInput.jsx | 9 +++- .../src/components/Milestones/Milestones.jsx | 23 ++++++--- frontend/src/hooks/useFetch.jsx | 2 +- 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 79b138464..7d3edfa82 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -36,3 +36,8 @@ export const milestoneAddButtonFlagState = atom({ key: "milestoneAddButtonFlagState", default: false, }); + +export const milestoneUpdateState = atom({ + key: "milestoneAddButtonFlagState", + default: false, +}); diff --git a/frontend/src/components/Milestones/MilestoneCard.jsx b/frontend/src/components/Milestones/MilestoneCard.jsx index 9b6af0b18..e464c72cc 100644 --- a/frontend/src/components/Milestones/MilestoneCard.jsx +++ b/frontend/src/components/Milestones/MilestoneCard.jsx @@ -1,3 +1,4 @@ +import { useState } from "react"; import styled from "styled-components"; import { StyledFlexCard } from "styles/StyledCards"; import { ReactComponent as Milestone } from "images/milestone.svg"; @@ -6,9 +7,34 @@ import { ReactComponent as Trash } from "images/trash.svg"; import { ReactComponent as EditIcon } from "images/edit.svg"; import getPercent from "util/getPercent"; import theme from "styles/theme"; +import useFetch from "hooks/useFetch"; +import API from "util/API"; +import fetchData from "util/fetchData"; +import { + milestoneAddButtonFlagState, + milestoneUpdateState, +} from "RecoilStore/Atoms"; +import { useRecoilState } from "recoil"; const MilestoneCard = ({ data }) => { const { id, title, description, dueDate, openIssues, closedIssues } = data; + const [_, update] = useRecoilState(milestoneUpdateState); + const [milestoneAddBtn, setMilestoneAddBtn] = useRecoilState( + milestoneAddButtonFlagState + ); + const deleteMilestone = async () => { + await fetchData(API.milestonesId(id), "DELETE"); + setMilestoneAddBtn(false); + }; + + const handleClose = () => {}; + + const handleEdit = () => {}; + + const handleDelete = () => { + deleteMilestone(); + update(!_); + }; return ( @@ -25,15 +51,24 @@ const MilestoneCard = ({ data }) => { - theme.grayScale.label}> + theme.grayScale.label} + onClick={handleClose} + > 닫기 - theme.grayScale.label}> + theme.grayScale.label} + onClick={handleEdit} + > 편집 - theme.colors.red}> + theme.colors.red} + onClick={handleDelete} + > 삭제 @@ -120,11 +155,15 @@ const ProgressWrapper = styled.div` /* margin-left: 30px; */ `; -const EditBtn = styled.div` +const EditBtn = styled.button` padding: 0 ${({ theme }) => theme.fontSizes.xl}; color: ${props => props._color}; :last-child { padding-right: 0; padding-left: ${({ theme }) => theme.fontSizes.xl}; } + background-color: ${({ theme }) => theme.grayScale.off_white}; + :hover { + background-color: ${({ theme }) => theme.grayScale.background}; + } `; diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index f905ec2c8..b7144a99a 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -3,8 +3,11 @@ import { useState, useCallback } from "react"; import AddButton from "components/common/Button/AddButton"; import useFetch from "hooks/useFetch"; import API from "util/API"; -import { useSetRecoilState } from "recoil"; -import { milestoneAddButtonFlagState } from "RecoilStore/Atoms"; +import { useSetRecoilState, useRecoilState } from "recoil"; +import { + milestoneAddButtonFlagState, + milestoneUpdateState, +} from "RecoilStore/Atoms"; const MilestoneInput = () => { const [inputData, setInputData] = useState({}); @@ -12,6 +15,7 @@ const MilestoneInput = () => { const setMilestoneAddButtonFlag = useSetRecoilState( milestoneAddButtonFlagState ); + const [_, update] = useRecoilState(milestoneUpdateState); const { res, fetchData } = useFetch( API.milestones(), "POST", @@ -43,6 +47,7 @@ const MilestoneInput = () => { const handleSubmit = () => { fetchData(); setMilestoneAddButtonFlag(false); + update(); }; return ( diff --git a/frontend/src/components/Milestones/Milestones.jsx b/frontend/src/components/Milestones/Milestones.jsx index 74de77543..d0b4cf2ed 100644 --- a/frontend/src/components/Milestones/Milestones.jsx +++ b/frontend/src/components/Milestones/Milestones.jsx @@ -2,13 +2,20 @@ import { useState, useEffect } from "react"; import MilestonesHeader from "./MilestonesHeader"; import MilestoneCard from "./MilestoneCard"; import MilestoneInput from "./MilestoneInput"; -import { milestoneAddButtonFlagState } from "RecoilStore/Atoms"; -import { useRecoilValue } from "recoil"; +import { + milestoneAddButtonFlagState, + milestoneUpdateState, +} from "RecoilStore/Atoms"; +import { useRecoilValue, useRecoilState } from "recoil"; import API from "util/API"; import fetchData from "util/fetchData"; const Milestones = () => { - const milestoneAddBtn = useRecoilValue(milestoneAddButtonFlagState); + const [milestoneAddBtn, setMilestoneAddBtn] = useRecoilState( + milestoneAddButtonFlagState + ); + const [_, update] = useRecoilState(milestoneUpdateState); + const [milestone, setMilestone] = useState(); const fetchMilestones = async () => { @@ -21,6 +28,10 @@ const Milestones = () => { fetchMilestones(); }, [milestoneAddBtn]); + useEffect(() => { + fetchMilestones(); + }, []); + return ( <> {milestoneAddBtn ? ( @@ -32,9 +43,9 @@ const Milestones = () => { <> )} {milestone && - milestone - .map((milestone, i) => ) - .reverse()} + milestone.map((milestone, i) => ( + + ))} ); }; diff --git a/frontend/src/hooks/useFetch.jsx b/frontend/src/hooks/useFetch.jsx index 2bc1c64f8..be383878e 100644 --- a/frontend/src/hooks/useFetch.jsx +++ b/frontend/src/hooks/useFetch.jsx @@ -44,7 +44,7 @@ const useFetch = (url, method, callback, reqData = null) => { useEffect(() => { fetchData(); - }, []); + }, [url]); return { status, fetchData }; }; From 913d20d64ad249d33361bd660dc8d872c267564a Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Sun, 20 Jun 2021 23:02:04 +0900 Subject: [PATCH 52/71] =?UTF-8?q?refactor:=20LabelInput=20useReducer?= =?UTF-8?q?=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelCard.jsx | 2 +- frontend/src/components/Labels/LabelInput.jsx | 80 +++++++++++-------- frontend/src/components/common/LabelBadge.jsx | 6 +- frontend/src/data.js | 2 +- 4 files changed, 50 insertions(+), 40 deletions(-) diff --git a/frontend/src/components/Labels/LabelCard.jsx b/frontend/src/components/Labels/LabelCard.jsx index 83fa7a79d..dd32c2f61 100644 --- a/frontend/src/components/Labels/LabelCard.jsx +++ b/frontend/src/components/Labels/LabelCard.jsx @@ -14,7 +14,7 @@ const LabelCard = () => { diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index bd9eccf9a..eef495638 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -1,65 +1,72 @@ import styled from "styled-components"; -import { DisplayFlex, CenterAi, CenterJcAi } from "styles/StyledLayout "; +import { DisplayFlex, CenterAi } from "styles/StyledLayout "; import { ReactComponent as RefreshIcon } from "images/refresh-ccw.svg"; import { ReactComponent as XIcon } from "images/x-square.svg"; import { ReactComponent as EditIcon } from "images/edit.svg"; import { ReactComponent as PlusIcon } from "images/plus.svg"; -import { useState, useEffect } from "react"; +import { useEffect, useReducer } from "react"; import LabelBadge from "components/common/LabelBadge"; import theme from "styles/theme"; import { labelData } from "data"; import useDebounce from "hooks/useDebounce"; const LabelInput = ({ isEditor }) => { - //🔥아래 상태 한번에 관리할까 말까 고민중⭐️ - const initLabelState = { - name: null, - description: null, - bgColor: null, - textColor: null, - }; - const [input, setInput] = useState(""); - const [textColor, setTextColor] = useState(false); - const [backGroundColor, setBackGroundColor] = useState( - theme.grayScale.input_background - ); - const [labelName, setLabelName] = useState("레이블 이름"); - const [labelDescription, setLabelDescription] = useState(""); const { creatorTitle, editorTitle, inputTitles, - bgColorTitles, + backgroundColorTitle, textColorTitles, buttons, } = labelData; - console.log(textColor); + + const initLabelState = { + name: "레이블 이름", + description: null, + backgroundColor: theme.grayScale.input_background, + textColor: false, + }; + const reducer = (state, { type, payload }) => { + switch (type) { + case "name": + return { ...state, name: payload }; + case "description": + return { ...state, description: payload }; + case "backgroundColor": + return { ...state, backgroundColor: payload }; + case "textColor": + return { ...state, textColor: payload }; + } + }; + const [labelState, dispatch] = useReducer(reducer, initLabelState); const handleClickRadioButton = event => { - const value = event.target.value; - setTextColor(value); + dispatch({ type: "textColor", payload: event.target.value }); }; + const handleChangeColor = event => { + //디바운스 필요(유저가 입력하고 1초 뒤에 set 하도록) + dispatch({ type: "backgroundColor", payload: event.target.value }); + }; + const test = useDebounce(labelState.description, 1000); - const test = useDebounce(input, 1000); //커스텀 훅은 컴포넌트 안에서 호출되어야 하는 부분 고려! - console.log(test); - console.log(backGroundColor); const handleTypingName = event => { if (event.target.id === "0") { - const textInput = event.target.value; - setLabelName(textInput); + dispatch({ type: "name", payload: event.target.value }); } else { - //🔥description 해결중 : 작성 후 1초 뒤에 set되면서 리렌더링 되도록 하고 싶음(디바운스) - setInput(event.target.value); - setLabelDescription(input); + // 디바운스 필요(유저가 입력하고 1초 뒤에 set 하도록) + dispatch({ type: "description", payload: event.target.value }); } }; const getFontColor = () => { - return textColor === "light" + return labelState.textColor === "light" ? theme.grayScale.off_white : theme.grayScale.black; }; const changeColor = () => { const randomColor = Math.floor(Math.random() * 16777215).toString(16); - setBackGroundColor(`#${randomColor}`); + dispatch({ + type: "backgroundColor", + payload: `#${randomColor}`, + }); }; return ( @@ -68,9 +75,9 @@ const LabelInput = ({ isEditor }) => { @@ -87,8 +94,11 @@ const LabelInput = ({ isEditor }) => { ))} - {bgColorTitles} - + {backgroundColorTitle} + @@ -100,7 +110,7 @@ const LabelInput = ({ isEditor }) => { diff --git a/frontend/src/components/common/LabelBadge.jsx b/frontend/src/components/common/LabelBadge.jsx index 7c7269124..29856493e 100644 --- a/frontend/src/components/common/LabelBadge.jsx +++ b/frontend/src/components/common/LabelBadge.jsx @@ -1,8 +1,8 @@ import styled from "styled-components"; -const LabelBadge = ({ text, fontColor, bgColor }) => { +const LabelBadge = ({ text, fontColor, backgroundColor }) => { return ( - + {text} ); @@ -16,7 +16,7 @@ const LabelBadgeLayout = styled.div` height: ${({ theme }) => theme.buttonHeights.small}; padding: 0px 16px; border-radius: 30px; - background: ${props => props.bgColor}; + background: ${props => props.backgroundColor}; color: ${props => props.fontColor}; `; diff --git a/frontend/src/data.js b/frontend/src/data.js index 3c379e752..d1f9c6409 100644 --- a/frontend/src/data.js +++ b/frontend/src/data.js @@ -38,7 +38,7 @@ export const labelData = { creatorTitle: "새로운 레이블 추가", editorTitle: "레이블 편집", inputTitles: ["레이블 이름", "설명(선택)"], - bgColorTitles: "배경 색상", + backgroundColorTitle: "배경 색상", textColorTitles: "텍스트 색상", buttons: { cancel: "취소", From c952533b082e6442015d303d1dd16ebab84a4e32 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 21 Jun 2021 00:35:14 +0900 Subject: [PATCH 53/71] =?UTF-8?q?feat:=20PUT=20useFetch=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Milestones/MilestoneCard.jsx | 126 ++++++++++-------- .../components/Milestones/MilestoneInput.jsx | 51 +++++-- frontend/src/hooks/useFetch.jsx | 4 +- 3 files changed, 116 insertions(+), 65 deletions(-) diff --git a/frontend/src/components/Milestones/MilestoneCard.jsx b/frontend/src/components/Milestones/MilestoneCard.jsx index e464c72cc..ce94b0641 100644 --- a/frontend/src/components/Milestones/MilestoneCard.jsx +++ b/frontend/src/components/Milestones/MilestoneCard.jsx @@ -15,10 +15,12 @@ import { milestoneUpdateState, } from "RecoilStore/Atoms"; import { useRecoilState } from "recoil"; +import MilestoneInput from "./MilestoneInput"; const MilestoneCard = ({ data }) => { const { id, title, description, dueDate, openIssues, closedIssues } = data; - const [_, update] = useRecoilState(milestoneUpdateState); + const [update, forceUpdate] = useRecoilState(milestoneUpdateState); + const [editMode, setEditMode] = useState(false); const [milestoneAddBtn, setMilestoneAddBtn] = useRecoilState( milestoneAddButtonFlagState ); @@ -29,65 +31,85 @@ const MilestoneCard = ({ data }) => { const handleClose = () => {}; - const handleEdit = () => {}; + const handleEdit = () => { + setEditMode(true); + }; const handleDelete = () => { deleteMilestone(); - update(!_); + forceUpdate(!update); }; return ( - - - - - - - {title} - - {dueDate} - - {description} - - - - theme.grayScale.label} - onClick={handleClose} - > - - 닫기 - - theme.grayScale.label} - onClick={handleEdit} - > - - 편집 - - theme.colors.red} - onClick={handleDelete} - > - - 삭제 - - -
- - - - - {getPercent(openIssues, closedIssues)}% + <> + {editMode ? ( + + ) : ( + + + - 열린 이슈 {openIssues}{" "} - 닫힌 이슈 {closedIssues} + + + {title} + + {dueDate} - -
-
-
-
+ {description} + + + + theme.grayScale.label} + onClick={handleClose} + > + + 닫기 + + theme.grayScale.label} + onClick={handleEdit} + > + + 편집 + + theme.colors.red} + onClick={handleDelete} + > + + 삭제 + + +
+ + + + + {getPercent(openIssues, closedIssues)}% + + 열린 이슈 {openIssues}{" "} + 닫힌 이슈 {closedIssues} + + +
+
+
+
+ )} + ); }; diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index b7144a99a..406b0f241 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -9,20 +9,35 @@ import { milestoneUpdateState, } from "RecoilStore/Atoms"; -const MilestoneInput = () => { +const MilestoneInput = ({ + title, + dueDate, + description, + id, + editMode, + setEditMode, +}) => { const [inputData, setInputData] = useState({}); const [milestoneData, setMilestoneData] = useState(); const setMilestoneAddButtonFlag = useSetRecoilState( milestoneAddButtonFlagState ); - const [_, update] = useRecoilState(milestoneUpdateState); - const { res, fetchData } = useFetch( + const [update, forceUpdate] = useRecoilState(milestoneUpdateState); + + const { postRes, fetchData: postData } = useFetch( API.milestones(), "POST", setMilestoneData, inputData ); + const { putRes, fetchData: putData } = useFetch( + API.milestonesId(id), + "PUT", + setMilestoneData, + inputData + ); + const handleTitleChange = e => { setInputData({ ...inputData, @@ -45,33 +60,49 @@ const MilestoneInput = () => { }; const handleSubmit = () => { - fetchData(); + postData(); setMilestoneAddButtonFlag(false); - update(); + forceUpdate(!update); }; + const handleEdit = () => { + putData(); + setMilestoneAddButtonFlag(false); + // setEditMode(false); + forceUpdate(!update); + }; + + console.log(editMode); + return ( -
새로운 마일스톤 추가
+
{editMode ? "마일스톤 편집" : "새로운 마일스톤 추가"}
- + - +
); diff --git a/frontend/src/hooks/useFetch.jsx b/frontend/src/hooks/useFetch.jsx index 3d9115096..318e79cf8 100644 --- a/frontend/src/hooks/useFetch.jsx +++ b/frontend/src/hooks/useFetch.jsx @@ -5,7 +5,7 @@ import fetchData from "util/fetchData"; const useFetch = (url, method, callback, reqData = null) => { const [status, setStatus] = useState("대기 중"); const [error, setError] = useState(null); - console.log("useFetch initiated"); + console.log(method, "initiated"); const option = method === "GET" @@ -24,7 +24,6 @@ const useFetch = (url, method, callback, reqData = null) => { body: JSON.stringify(reqData), }; - const fetchData = async () => { console.log("fetchData func initiated"); try { @@ -49,7 +48,6 @@ const useFetch = (url, method, callback, reqData = null) => { }, [url]); return { status, fetchData }; - }; export default useFetch; From 268466091f8c5af9d791e43d5c0c573943ce3dc5 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 21 Jun 2021 01:07:46 +0900 Subject: [PATCH 54/71] =?UTF-8?q?WIP:=20post,=20put=20=EC=9E=91=EC=97=85?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Milestones/MilestoneInput.jsx | 29 +++++++++---------- .../src/components/Milestones/Milestones.jsx | 1 + 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index 406b0f241..00445c503 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -8,6 +8,7 @@ import { milestoneAddButtonFlagState, milestoneUpdateState, } from "RecoilStore/Atoms"; +import fetchData from "util/fetchData"; const MilestoneInput = ({ title, @@ -24,19 +25,13 @@ const MilestoneInput = ({ ); const [update, forceUpdate] = useRecoilState(milestoneUpdateState); - const { postRes, fetchData: postData } = useFetch( - API.milestones(), - "POST", - setMilestoneData, - inputData - ); + const putMilestone = async () => { + await fetchData(API.milestonesId(id), "PUT", inputData); + }; - const { putRes, fetchData: putData } = useFetch( - API.milestonesId(id), - "PUT", - setMilestoneData, - inputData - ); + const postMilestone = async () => { + await fetchData(API.milestonesId(id), "POST", inputData); + }; const handleTitleChange = e => { setInputData({ @@ -60,16 +55,18 @@ const MilestoneInput = ({ }; const handleSubmit = () => { - postData(); + console.log("submit clicked"); + postMilestone(); setMilestoneAddButtonFlag(false); - forceUpdate(!update); + // forceUpdate(!update); }; const handleEdit = () => { - putData(); + console.log("edit clicked"); + putMilestone(); setMilestoneAddButtonFlag(false); // setEditMode(false); - forceUpdate(!update); + // forceUpdate(!update); }; console.log(editMode); diff --git a/frontend/src/components/Milestones/Milestones.jsx b/frontend/src/components/Milestones/Milestones.jsx index d0b4cf2ed..32c503eef 100644 --- a/frontend/src/components/Milestones/Milestones.jsx +++ b/frontend/src/components/Milestones/Milestones.jsx @@ -30,6 +30,7 @@ const Milestones = () => { useEffect(() => { fetchMilestones(); + setMilestoneAddBtn(false); }, []); return ( From ba6a96ea36fac222bcb4355a36489f2b0610b57c Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Mon, 21 Jun 2021 01:20:34 +0900 Subject: [PATCH 55/71] =?UTF-8?q?WIP:=20merge=20=ED=9B=84=20Lable=20page?= =?UTF-8?q?=20=EC=9E=91=EC=97=85=20=EC=A4=91(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelCard.jsx | 3 +- frontend/src/components/Labels/LabelInput.jsx | 53 +++++++++++++------ frontend/src/components/Labels/Labels.jsx | 19 ++++--- .../components/common/Button/CancelButton.jsx | 4 +- frontend/src/components/common/Navigator.jsx | 8 ++- frontend/src/styles/StyledButtons.jsx | 29 +++++----- 6 files changed, 78 insertions(+), 38 deletions(-) diff --git a/frontend/src/components/Labels/LabelCard.jsx b/frontend/src/components/Labels/LabelCard.jsx index dd32c2f61..11b920196 100644 --- a/frontend/src/components/Labels/LabelCard.jsx +++ b/frontend/src/components/Labels/LabelCard.jsx @@ -6,7 +6,8 @@ import { ReactComponent as TrashIcon } from "images/trash.svg"; import theme from "styles/theme"; import { CenterJcAi, CenterAi } from "styles/StyledLayout "; -const LabelCard = () => { +const LabelCard = ({ name, description, colors }) => { + // const { backgroundColor, textColor } = colors; return ( <> diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index eef495638..f23e61904 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -9,6 +9,9 @@ import LabelBadge from "components/common/LabelBadge"; import theme from "styles/theme"; import { labelData } from "data"; import useDebounce from "hooks/useDebounce"; +import API from "util/API"; +import fetchData from "util/fetchData"; +import CancelButton from "components/common/Button/CancelButton"; const LabelInput = ({ isEditor }) => { const { creatorTitle, @@ -25,6 +28,7 @@ const LabelInput = ({ isEditor }) => { backgroundColor: theme.grayScale.input_background, textColor: false, }; + const reducer = (state, { type, payload }) => { switch (type) { case "name": @@ -56,6 +60,25 @@ const LabelInput = ({ isEditor }) => { dispatch({ type: "description", payload: event.target.value }); } }; + const handleSubmit = async () => { + const testData = { + name: "feature", + description: "새 기능", + colors: { + backgroundColor: "#000000", + textColor: "#FFFFFF", + }, + }; + if (isEditor) { + console.log("editor~"); + const res = await fetchData(API.labels(), "POST", testData); + console.log(res); + } else { + console.log("신규~"); + const res = await fetchData(API.labels(), "POST", testData); + console.log("res", res); + } + }; const getFontColor = () => { return labelState.textColor === "light" ? theme.grayScale.off_white @@ -128,7 +151,7 @@ const LabelInput = ({ isEditor }) => { {buttons.cancel} )} - + {isEditor ? ( ) : ( @@ -186,20 +209,20 @@ const TextInputContainer = styled(CenterAi)` color: ${({ theme }) => theme.grayScale.title_active}; `; -const CancelButton = styled.div` - display: flex; - justify-content: center; - align-items: center; - padding: 0px 16px; - margin: 0 3px; - width: 120px; - height: 40px; - color: ${theme.colors.blue}; - background: ${theme.colors.off_white}; - border: 2px solid ${theme.colors.blue}; - border-radius: 11px; - cursor: pointer; -`; +// const CancelButton = styled.div` +// display: flex; +// justify-content: center; +// align-items: center; +// padding: 0px 16px; +// margin: 0 3px; +// width: 120px; +// height: 40px; +// color: ${theme.colors.blue}; +// background: ${theme.colors.off_white}; +// border: 2px solid ${theme.colors.blue}; +// border-radius: 11px; +// cursor: pointer; +// `; const SubmitButton = styled.div` display: flex; diff --git a/frontend/src/components/Labels/Labels.jsx b/frontend/src/components/Labels/Labels.jsx index 9da147f2e..9fd9e9734 100644 --- a/frontend/src/components/Labels/Labels.jsx +++ b/frontend/src/components/Labels/Labels.jsx @@ -3,13 +3,22 @@ import LabelCard from "./LabelCard"; import LabelInput from "./LabelInput"; import { StyledGridTitleCard } from "styles/StyledCards"; import useFetch from "hooks/useFetch"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import API from "util/API"; +import fetchData from "util/fetchData"; const Labels = () => { const [LabelData, setLabelData] = useState(); - const status = useFetch(API.labels(), "GET", setLabelData); - console.log(LabelData, "status", status); + // const status = useFetch(API.labels(), "GET", setLabelData); + // console.log(LabelData, "status", status); + const getLabelData = async () => { + const data = await fetchData(API.labels(), "GET"); + setLabelData(data); + }; + + useEffect(() => { + getLabelData(); + }, []); return ( <> @@ -17,10 +26,8 @@ const Labels = () => { N개의 레이블 - + - - ); }; diff --git a/frontend/src/components/common/Button/CancelButton.jsx b/frontend/src/components/common/Button/CancelButton.jsx index b65fb566e..bb1aeb86c 100644 --- a/frontend/src/components/common/Button/CancelButton.jsx +++ b/frontend/src/components/common/Button/CancelButton.jsx @@ -1,9 +1,9 @@ -import { StyledCancelButton } from "styles/StyledButtons"; +import { StyledWhiteButton } from "styles/StyledButtons"; const CancelButton = ({ clickEvent, children }) => { return ( <> - {children} + {children} ); }; diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index 24f7453f7..685eb40f1 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -7,8 +7,9 @@ import { milestoneButtonFlagState, milestoneAddButtonFlagState, } from "RecoilStore/Atoms"; - +import { useState } from "react"; const Navigator = () => { + const [isAddButton, setIsAddButton] = useState(true); const [milestoneFlag, setMilestoneFlag] = useRecoilState( milestoneButtonFlagState ); @@ -40,7 +41,10 @@ const Navigator = () => { labelClickEvent={handleLabelClick} isMainPage={false} /> - + ); }; diff --git a/frontend/src/styles/StyledButtons.jsx b/frontend/src/styles/StyledButtons.jsx index ca37db805..4331a9008 100644 --- a/frontend/src/styles/StyledButtons.jsx +++ b/frontend/src/styles/StyledButtons.jsx @@ -2,21 +2,20 @@ import styled from "styled-components"; import Button from "@material-ui/core/Button"; export const TabButton = styled(Button)` - width: ${(props) => props._width}; + width: ${props => props._width}; height: ${({ theme }) => theme.buttonHeights.base}; font-size: ${({ theme }) => theme.fontSizes.xs}; font-weight: bold; color: ${({ theme }) => theme.grayScale.label}; border: 1px solid - ${(props) => - props._border === "none" ? "none" : props.theme.grayScale.line}; - border-radius: ${(props) => + ${props => (props._border === "none" ? "none" : props.theme.grayScale.line)}; + border-radius: ${props => props._radius === "right" ? props.theme.border_radius_mix.right : props._radius === "left" ? props.theme.border_radius_mix.left : props.theme.border_radius_mix.all}; - background-color: ${(props) => + background-color: ${props => props.bgColor && !props.isMainPage ? props.theme.grayScale.line : props.theme.grayScale.background}; @@ -49,11 +48,17 @@ export const StyledLoginButton = styled(Button)` } `; -export const StyledCancelButton = styled(Button)` - width: ${(props) => props._width}; - height: ${({ theme }) => theme.buttonHeights.small}; - color: ${({ theme }) => theme.grayScale.label}; - font-weight: bold; - font-size: ${({ theme }) => theme.fontSizes.xs}; - border-radius: ${({ theme }) => theme.border_radius.small}; +export const StyledWhiteButton = styled(Button)` + display: flex; + justify-content: center; + align-items: center; + padding: 0px 16px; + margin: 0 3px; + width: 120px; + height: 40px; + color: ${({ theme }) => theme.colors.blue}; + background: ${({ theme }) => theme.colors.off_white}; + border: 2px solid ${({ theme }) => theme.colors.blue}; + border-radius: 11px; + cursor: pointer; `; From ab4e780b9474adb02a1220c1e65523cef6b38674 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Mon, 21 Jun 2021 22:07:25 +0900 Subject: [PATCH 56/71] =?UTF-8?q?refactor:=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20blue,=20white=20buttons?= =?UTF-8?q?=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/Button/AddButton.jsx | 19 ------ .../components/common/Button/BlueButtons.jsx | 63 ++++++++++++++++++ .../components/common/Button/CancelButton.jsx | 11 ---- .../components/common/Button/SubmitButton.jsx | 11 ---- .../components/common/Button/WhiteButtons.jsx | 66 +++++++++++++++++++ .../src/components/common/CloseButton.jsx | 5 -- frontend/src/styles/StyledButtons.jsx | 30 +-------- frontend/src/styles/theme.js | 1 + 8 files changed, 131 insertions(+), 75 deletions(-) delete mode 100644 frontend/src/components/common/Button/AddButton.jsx create mode 100644 frontend/src/components/common/Button/BlueButtons.jsx delete mode 100644 frontend/src/components/common/Button/CancelButton.jsx delete mode 100644 frontend/src/components/common/Button/SubmitButton.jsx create mode 100644 frontend/src/components/common/Button/WhiteButtons.jsx delete mode 100644 frontend/src/components/common/CloseButton.jsx diff --git a/frontend/src/components/common/Button/AddButton.jsx b/frontend/src/components/common/Button/AddButton.jsx deleted file mode 100644 index 2cf1e1e8a..000000000 --- a/frontend/src/components/common/Button/AddButton.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import { AddBtn } from "styles/StyledButtons"; -import { ReactComponent as PlusIcon } from "images/plus.svg"; -import styled from "styled-components"; -import theme from "styles/theme"; -const AddButton = ({ text, clickEvent }) => { - return ( - <> - - - {text} - - - ); -}; -const ButtonText = styled.div` - padding: 0 4%; -`; - -export default AddButton; diff --git a/frontend/src/components/common/Button/BlueButtons.jsx b/frontend/src/components/common/Button/BlueButtons.jsx new file mode 100644 index 000000000..308ce51f1 --- /dev/null +++ b/frontend/src/components/common/Button/BlueButtons.jsx @@ -0,0 +1,63 @@ +import Button from "@material-ui/core/Button"; +import { ReactComponent as EditIcon } from "images/edit.svg"; +import { ReactComponent as PlusIcon } from "images/plus.svg"; +import styled from "styled-components"; +import theme from "styles/theme"; + +const BlueButtons = ({ text, icon, size, clickHandler }) => { + const getIcon = () => { + switch (icon) { + case "plus": { + return ; + } + case "edit": { + return ; + } + case "none": { + return <>; + } + default: { + console.error("unhandled icon Type🤦‍♀️"); + } + } + }; + + const getWidth = () => { + switch (size) { + case "m": { + return theme.buttonWidths.baseS; + } + case "l": { + return theme.buttonWidths.lg; + } + default: { + console.error("unhandled width Type🤦‍♀️"); + } + } + }; + + return ( + + {getIcon()} + {text} + + ); +}; + +const BlueButton = styled(Button)` + width: ${props => props._width}; + height: ${({ theme }) => theme.buttonHeights.base}; + font-size: ${({ theme }) => theme.fontSizes.xs}; + font-weight: bold; + color: ${({ theme }) => theme.grayScale.off_white}; + background-color: ${({ theme }) => theme.colors.blue}; + border-radius: ${({ theme }) => theme.border_radius.base}; + cursor: pointer; + &:hover { + background-color: ${({ theme }) => theme.colors.dark_blue}; + } +`; +const ButtonText = styled.div` + padding: 0 4%; +`; +export default BlueButtons; diff --git a/frontend/src/components/common/Button/CancelButton.jsx b/frontend/src/components/common/Button/CancelButton.jsx deleted file mode 100644 index bb1aeb86c..000000000 --- a/frontend/src/components/common/Button/CancelButton.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import { StyledWhiteButton } from "styles/StyledButtons"; - -const CancelButton = ({ clickEvent, children }) => { - return ( - <> - {children} - - ); -}; - -export default CancelButton; diff --git a/frontend/src/components/common/Button/SubmitButton.jsx b/frontend/src/components/common/Button/SubmitButton.jsx deleted file mode 100644 index 5dd81f196..000000000 --- a/frontend/src/components/common/Button/SubmitButton.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import { AddBtn } from "styles/StyledButtons"; - -const SubmitButton = ({ clickevent, children }) => { - return ( - <> - {children} - - ); -}; - -export default SubmitButton; diff --git a/frontend/src/components/common/Button/WhiteButtons.jsx b/frontend/src/components/common/Button/WhiteButtons.jsx new file mode 100644 index 000000000..bad48f45d --- /dev/null +++ b/frontend/src/components/common/Button/WhiteButtons.jsx @@ -0,0 +1,66 @@ +import Button from "@material-ui/core/Button"; +import { ReactComponent as XIcon } from "images/x-square.svg"; +import { ReactComponent as EditIcon } from "images/edit.svg"; +import { ReactComponent as PaperIcon } from "images/paperclip.svg"; +import styled from "styled-components"; +import theme from "styles/theme"; + +const WhiteButtons = ({ text, icon, size, clickHandler }) => { + const getIcon = () => { + switch (icon) { + case "edit": { + return ; + } + case "cancel": { + return ; + } + case "paper": { + return ; + } + case "none": { + return <>; + } + default: { + console.error("unhandled icon Type🤦‍♀️"); + } + } + }; + + const getWidth = () => { + switch (size) { + case "m": { + return theme.buttonWidths.baseS; + } + case "l": { + return theme.buttonWidths.lg; + } + default: { + console.error("unhandled width Type🤦‍♀️"); + } + } + }; + + return ( + + {getIcon()} + {text} + + ); +}; + +const WhiteButton = styled(Button)` + width: ${props => props._width}; + height: ${({ theme }) => theme.buttonHeights.base}; + font-size: ${({ theme }) => theme.fontSizes.xs}; + font-weight: bold; + color: ${({ theme }) => theme.colors.blue}; + background: ${({ theme }) => theme.colors.off_white}; + border: 2px solid ${({ theme }) => theme.colors.blue}; + border-radius: 11px; + cursor: pointer; +`; +const ButtonText = styled.div` + padding: 0 4%; +`; + +export default WhiteButtons; diff --git a/frontend/src/components/common/CloseButton.jsx b/frontend/src/components/common/CloseButton.jsx deleted file mode 100644 index 5d48a38f7..000000000 --- a/frontend/src/components/common/CloseButton.jsx +++ /dev/null @@ -1,5 +0,0 @@ -const CloseButton = () => { - return
; -}; - -export default CloseButton; diff --git a/frontend/src/styles/StyledButtons.jsx b/frontend/src/styles/StyledButtons.jsx index 4331a9008..35479b31e 100644 --- a/frontend/src/styles/StyledButtons.jsx +++ b/frontend/src/styles/StyledButtons.jsx @@ -23,21 +23,8 @@ export const TabButton = styled(Button)` theme.grayScale.background}; //str넣었는데 str넣으라고 오류뜸 */ `; -export const AddBtn = styled(Button)` - width: 160px; - height: ${({ theme }) => theme.buttonHeights.base}; - font-size: ${({ theme }) => theme.fontSizes.xs}; - font-weight: bold; - background-color: ${({ theme }) => theme.colors.blue}; - color: ${({ theme }) => theme.grayScale.off_white}; - border-radius: 11px; - &:hover { - background-color: ${({ theme }) => theme.colors.dark_blue}; - } -`; - export const StyledLoginButton = styled(Button)` - width: 340px; + width: ${({ theme }) => theme.buttonWidths.xl}; height: ${({ theme }) => theme.buttonHeights.lg}; font-size: ${({ theme }) => theme.fontSizes.base}; background-color: ${({ theme }) => theme.grayScale.title_active}; @@ -47,18 +34,3 @@ export const StyledLoginButton = styled(Button)` background-color: ${({ theme }) => theme.grayScale.body}; } `; - -export const StyledWhiteButton = styled(Button)` - display: flex; - justify-content: center; - align-items: center; - padding: 0px 16px; - margin: 0 3px; - width: 120px; - height: 40px; - color: ${({ theme }) => theme.colors.blue}; - background: ${({ theme }) => theme.colors.off_white}; - border: 2px solid ${({ theme }) => theme.colors.blue}; - border-radius: 11px; - cursor: pointer; -`; diff --git a/frontend/src/styles/theme.js b/frontend/src/styles/theme.js index 656f9d8dd..c69c553e2 100644 --- a/frontend/src/styles/theme.js +++ b/frontend/src/styles/theme.js @@ -9,6 +9,7 @@ const StyledSpaceBetween = css` const buttonWidths = { small: "100px", + baseS: "120px", base: "128px", lg: "160px", xl: "340px", From 7b2a022e9a2916417a781e7ef9b2e86c2b515c2d Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Mon, 21 Jun 2021 22:09:59 +0900 Subject: [PATCH 57/71] =?UTF-8?q?refactor:=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81=20=ED=95=9C=20white,=20blue=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Issues/Menu/MenuFilterBar.jsx | 2 +- .../src/components/Issues/Menu/MenuTab.jsx | 4 +- frontend/src/components/Labels/LabelInput.jsx | 68 +++++-------------- .../components/Milestones/MilestoneInput.jsx | 4 +- .../src/components/NewIssues/NewIssueForm.jsx | 7 +- .../common/Button/DropDownButton.jsx | 1 - frontend/src/components/common/Navigator.jsx | 25 +++++-- 7 files changed, 47 insertions(+), 64 deletions(-) diff --git a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx index 803dff419..b5e5acf73 100644 --- a/frontend/src/components/Issues/Menu/MenuFilterBar.jsx +++ b/frontend/src/components/Issues/Menu/MenuFilterBar.jsx @@ -10,7 +10,7 @@ const MenuFilterBar = () => { const [isFilterClicked, setIsFilterClicked] = useState(false); const setClickedFilterState = useSetRecoilState(clickedFilterState); const filterBarInput = useRecoilValue(filterBarInputState); - console.log(filterBarInput); + const getFilterBarString = () => { return Object.entries(filterBarInput).reduce((acc, item) => { if (item[1]) { diff --git a/frontend/src/components/Issues/Menu/MenuTab.jsx b/frontend/src/components/Issues/Menu/MenuTab.jsx index bee8f65a2..43660569d 100644 --- a/frontend/src/components/Issues/Menu/MenuTab.jsx +++ b/frontend/src/components/Issues/Menu/MenuTab.jsx @@ -1,6 +1,6 @@ import styled from "styled-components"; import ButtonGroup from "components/common/Button/ButtonGroup"; -import AddButton from "components/common/Button/AddButton"; +import AddButton from "components/common/Button/BlueButtons"; import { Link } from "react-router-dom"; import { useSetRecoilState } from "recoil"; import { @@ -29,7 +29,7 @@ const MenuTab = () => { isMainPage={true} /> - +
); diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index f23e61904..162ff5baa 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -1,9 +1,6 @@ import styled from "styled-components"; import { DisplayFlex, CenterAi } from "styles/StyledLayout "; import { ReactComponent as RefreshIcon } from "images/refresh-ccw.svg"; -import { ReactComponent as XIcon } from "images/x-square.svg"; -import { ReactComponent as EditIcon } from "images/edit.svg"; -import { ReactComponent as PlusIcon } from "images/plus.svg"; import { useEffect, useReducer } from "react"; import LabelBadge from "components/common/LabelBadge"; import theme from "styles/theme"; @@ -11,7 +8,8 @@ import { labelData } from "data"; import useDebounce from "hooks/useDebounce"; import API from "util/API"; import fetchData from "util/fetchData"; -import CancelButton from "components/common/Button/CancelButton"; +import CancelButton from "components/common/Button/WhiteButtons"; +import SubmitButton from "components/common/Button/BlueButtons"; const LabelInput = ({ isEditor }) => { const { creatorTitle, @@ -70,13 +68,9 @@ const LabelInput = ({ isEditor }) => { }, }; if (isEditor) { - console.log("editor~"); const res = await fetchData(API.labels(), "POST", testData); - console.log(res); } else { - console.log("신규~"); const res = await fetchData(API.labels(), "POST", testData); - console.log("res", res); } }; const getFontColor = () => { @@ -146,19 +140,23 @@ const LabelInput = ({ isEditor }) => { {isEditor && ( - - - {buttons.cancel} - + + )} + {isEditor ? ( + + ) : ( + )} - - {isEditor ? ( - - ) : ( - - )} - {buttons.submit} - @@ -209,36 +207,6 @@ const TextInputContainer = styled(CenterAi)` color: ${({ theme }) => theme.grayScale.title_active}; `; -// const CancelButton = styled.div` -// display: flex; -// justify-content: center; -// align-items: center; -// padding: 0px 16px; -// margin: 0 3px; -// width: 120px; -// height: 40px; -// color: ${theme.colors.blue}; -// background: ${theme.colors.off_white}; -// border: 2px solid ${theme.colors.blue}; -// border-radius: 11px; -// cursor: pointer; -// `; - -const SubmitButton = styled.div` - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - padding: 0px 16px; - margin: 0 3px; - width: 120px; - height: 40px; - background: ${theme.colors.blue}; - color: ${theme.grayScale.off_white}; - border-radius: 11px; - cursor: pointer; -`; - const RadioButton = styled.input` cursor: pointer; `; diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index 00445c503..45f65f343 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -1,6 +1,6 @@ import styled from "styled-components"; import { useState, useCallback } from "react"; -import AddButton from "components/common/Button/AddButton"; +import AddButton from "components/common/Button/BlueButtons"; import useFetch from "hooks/useFetch"; import API from "util/API"; import { useSetRecoilState, useRecoilState } from "recoil"; @@ -98,6 +98,8 @@ const MilestoneInput = ({ diff --git a/frontend/src/components/NewIssues/NewIssueForm.jsx b/frontend/src/components/NewIssues/NewIssueForm.jsx index e0c56d24b..4aaea55d7 100644 --- a/frontend/src/components/NewIssues/NewIssueForm.jsx +++ b/frontend/src/components/NewIssues/NewIssueForm.jsx @@ -1,8 +1,6 @@ import styled from "styled-components"; import NewIssueInput from "./NewIssueInput"; import IssueCategoryList from "components/common/IssueCategoryList"; -import SubmitButton from "components/common/Button/SubmitButton"; -import CancelButton from "components/common/Button/CancelButton"; const NewIssueForm = () => { return ( @@ -12,8 +10,9 @@ const NewIssueForm = () => {
- x 작성 취소 - 완료 + {/* 스타일 코드 작성시 이부분 button 컴포넌트 적용 필요 */} + + ); diff --git a/frontend/src/components/common/Button/DropDownButton.jsx b/frontend/src/components/common/Button/DropDownButton.jsx index 32b85f60c..95b9798de 100644 --- a/frontend/src/components/common/Button/DropDownButton.jsx +++ b/frontend/src/components/common/Button/DropDownButton.jsx @@ -12,7 +12,6 @@ const DropDownButton = ({ text, clickEvent, width, border, radius }) => { _radius={radius} > {text} - {/* theme.grayScale.label} /> 적용 안 됨*/} diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index 685eb40f1..f04d56233 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -1,6 +1,7 @@ import styled from "styled-components"; import ButtonGroup from "./Button/ButtonGroup"; -import AddButton from "./Button/AddButton"; +import AddButton from "./Button/BlueButtons"; +import CancelButton from "components/common/Button/WhiteButtons"; import { useRecoilState } from "recoil"; import { labelButtonFlagState, @@ -8,6 +9,7 @@ import { milestoneAddButtonFlagState, } from "RecoilStore/Atoms"; import { useState } from "react"; + const Navigator = () => { const [isAddButton, setIsAddButton] = useState(true); const [milestoneFlag, setMilestoneFlag] = useRecoilState( @@ -30,6 +32,7 @@ const Navigator = () => { const handelAddClick = () => { if (milestoneFlag) setMilestoneAddBtnFlag(!milestoneAddBtnFlag); else if (!milestoneFlag) setMilestoneAddBtnFlag(false); + setIsAddButton(x => !x); }; return ( @@ -41,10 +44,22 @@ const Navigator = () => { labelClickEvent={handleLabelClick} isMainPage={false} /> - + + {isAddButton ? ( + + ) : ( + setIsAddButton(x => !x)} + /> + )} ); }; From f0e2ce138fa46ded460f95c414f28adfde7c3e80 Mon Sep 17 00:00:00 2001 From: "DESKTOP-O9GP521\\J" Date: Mon, 21 Jun 2021 22:16:46 +0900 Subject: [PATCH 58/71] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4=20put,=20post=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Milestones/MilestoneCard.jsx | 1 - .../components/Milestones/MilestoneInput.jsx | 34 ++++++++++++------- .../src/components/Milestones/Milestones.jsx | 7 ---- frontend/src/util/fetchData.js | 9 +++-- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/Milestones/MilestoneCard.jsx b/frontend/src/components/Milestones/MilestoneCard.jsx index ce94b0641..542412754 100644 --- a/frontend/src/components/Milestones/MilestoneCard.jsx +++ b/frontend/src/components/Milestones/MilestoneCard.jsx @@ -7,7 +7,6 @@ import { ReactComponent as Trash } from "images/trash.svg"; import { ReactComponent as EditIcon } from "images/edit.svg"; import getPercent from "util/getPercent"; import theme from "styles/theme"; -import useFetch from "hooks/useFetch"; import API from "util/API"; import fetchData from "util/fetchData"; import { diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index 00445c503..be2c9703e 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -1,7 +1,6 @@ import styled from "styled-components"; import { useState, useCallback } from "react"; import AddButton from "components/common/Button/AddButton"; -import useFetch from "hooks/useFetch"; import API from "util/API"; import { useSetRecoilState, useRecoilState } from "recoil"; import { @@ -18,22 +17,35 @@ const MilestoneInput = ({ editMode, setEditMode, }) => { - const [inputData, setInputData] = useState({}); + const [inputData, setInputData] = useState({ + title: title, + dueDate: dueDate, + description: description, + }); const [milestoneData, setMilestoneData] = useState(); const setMilestoneAddButtonFlag = useSetRecoilState( milestoneAddButtonFlagState ); const [update, forceUpdate] = useRecoilState(milestoneUpdateState); + const [titleInput, setTitleInput] = useState(title); + const [dateInput, setDateInput] = useState(dueDate); + const [descInput, setDescInput] = useState(description); + const putMilestone = async () => { await fetchData(API.milestonesId(id), "PUT", inputData); + setMilestoneAddButtonFlag(false); + setEditMode(false); + forceUpdate(); }; const postMilestone = async () => { - await fetchData(API.milestonesId(id), "POST", inputData); + await fetchData(API.milestones(), "POST", inputData); + setMilestoneAddButtonFlag(false); }; const handleTitleChange = e => { + setTitleInput(e.target.value); setInputData({ ...inputData, title: e.target.value, @@ -41,6 +53,7 @@ const MilestoneInput = ({ }; const handleDateChange = e => { + setDateInput(e.target.value); setInputData({ ...inputData, dueDate: e.target.value, @@ -48,6 +61,7 @@ const MilestoneInput = ({ }; const handleDescChange = e => { + setDescInput(e.target.value); setInputData({ ...inputData, description: e.target.value, @@ -55,20 +69,11 @@ const MilestoneInput = ({ }; const handleSubmit = () => { - console.log("submit clicked"); postMilestone(); setMilestoneAddButtonFlag(false); // forceUpdate(!update); }; - const handleEdit = () => { - console.log("edit clicked"); - putMilestone(); - setMilestoneAddButtonFlag(false); - // setEditMode(false); - // forceUpdate(!update); - }; - console.log(editMode); return ( @@ -80,6 +85,7 @@ const MilestoneInput = ({ type="text" placeholder={title ? title : "마일스톤 이름"} onChange={handleTitleChange} + value={title && titleInput} /> @@ -87,6 +93,7 @@ const MilestoneInput = ({ type="date" placeholder={dueDate ? dueDate : "완료일(선택) ex. YYYY-MM-DD"} onChange={handleDateChange} + value={dueDate && dateInput} /> @@ -94,11 +101,12 @@ const MilestoneInput = ({ type="text" placeholder={description ? description : "설명(선택)"} onChange={handleDescChange} + value={description && descInput} /> diff --git a/frontend/src/components/Milestones/Milestones.jsx b/frontend/src/components/Milestones/Milestones.jsx index 32c503eef..8e587ecb7 100644 --- a/frontend/src/components/Milestones/Milestones.jsx +++ b/frontend/src/components/Milestones/Milestones.jsx @@ -15,12 +15,10 @@ const Milestones = () => { milestoneAddButtonFlagState ); const [_, update] = useRecoilState(milestoneUpdateState); - const [milestone, setMilestone] = useState(); const fetchMilestones = async () => { const { milestones } = await fetchData(API.milestones(), "GET"); - console.log(milestones); setMilestone(milestones); }; @@ -28,11 +26,6 @@ const Milestones = () => { fetchMilestones(); }, [milestoneAddBtn]); - useEffect(() => { - fetchMilestones(); - setMilestoneAddBtn(false); - }, []); - return ( <> {milestoneAddBtn ? ( diff --git a/frontend/src/util/fetchData.js b/frontend/src/util/fetchData.js index bda5a767a..5cf659c9c 100644 --- a/frontend/src/util/fetchData.js +++ b/frontend/src/util/fetchData.js @@ -16,14 +16,17 @@ const fetchData = async (url, method, reqData) => { body: JSON.stringify(reqData), }; - console.log("fetchData func initiated"); + // console.log("fetchData func initiated"); try { + console.log("reqData:", reqData); + // console.log("option:", option); const res = await fetch(url, option); const resData = await res.json(); + // console.log("in useFetch :", resData); if (!res.ok) throw new Error(res.status); else { - console.log("in useFetch:", resData); - return resData; + // console.log("in useFetch:", resData); + return await resData; } } catch (error) { console.error("error occured"); From 44b7065eee59bc3bd83fd5a35f3731cdc76dac5b Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Tue, 22 Jun 2021 02:25:24 +0900 Subject: [PATCH 59/71] =?UTF-8?q?feat:=20GET=20=EA=B2=B0=EA=B3=BC=EB=A1=9C?= =?UTF-8?q?=20render=20=EB=B0=8F=20=EB=B2=84=ED=8A=BC=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=99=84=EC=84=B1(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 23 +++++- frontend/src/components/Labels/LabelCard.jsx | 70 ++++++++++++------- frontend/src/components/Labels/LabelInput.jsx | 56 ++++++++++++--- frontend/src/components/Labels/Labels.jsx | 30 +++++--- frontend/src/components/common/Navigator.jsx | 43 ++++++++---- frontend/src/util/fetchData.js | 6 +- 6 files changed, 160 insertions(+), 68 deletions(-) diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 7d3edfa82..08ecb0912 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -23,8 +23,8 @@ export const filterBarInputState = atom({ }); export const labelButtonFlagState = atom({ - key: "labelButtonFlag", - default: false, + key: "labelButtonFlagState", + default: true, }); export const milestoneButtonFlagState = atom({ @@ -41,3 +41,22 @@ export const milestoneUpdateState = atom({ key: "milestoneAddButtonFlagState", default: false, }); + +export const labelInitialData = atom({ + key: "labelInitialData", + default: null, +}); +export const labelAddButtonFlagState = atom({ + key: "labelAddButtonFlagState", + default: false, +}); + +export const labelEditButtonFlagState = atom({ + key: "labelEditButtonFlagState", + default: false, +}); + +export const navigatorAddButtonFlagState = atom({ + key: "navigatorAddButtonFlagState", + default: false, +}); diff --git a/frontend/src/components/Labels/LabelCard.jsx b/frontend/src/components/Labels/LabelCard.jsx index 11b920196..041807018 100644 --- a/frontend/src/components/Labels/LabelCard.jsx +++ b/frontend/src/components/Labels/LabelCard.jsx @@ -5,34 +5,52 @@ import { ReactComponent as EditIcon } from "images/edit.svg"; import { ReactComponent as TrashIcon } from "images/trash.svg"; import theme from "styles/theme"; import { CenterJcAi, CenterAi } from "styles/StyledLayout "; +import { labelInitialData, labelEditButtonFlagState } from "RecoilStore/Atoms"; +import { useRecoilValue, useSetRecoilState } from "recoil"; + +const LabelCard = ({ initialData }) => { + const { name, description, colors } = initialData; + const { backgroundColor, textColor } = colors; + + const setLabelEditBtnFlag = useSetRecoilState(labelEditButtonFlagState); + const handleEditButton = () => { + setLabelEditBtnFlag(x => !x); + }; + const handleDeleteButton = () => {}; -const LabelCard = ({ name, description, colors }) => { - // const { backgroundColor, textColor } = colors; return ( - <> - - - - - - - 구디의 모닝 알고리즘 100,000,000일차 ☀️ - - - - - theme.grayScale.label}> - 편집 - - - theme.colors.red}>삭제 - - - + initialData && ( + <> + + + + + + {description} + + + + theme.grayScale.label} + onClick={handleEditButton} + > + 편집 + + + theme.colors.red} + onClick={handleDeleteButton} + > + 삭제 + + + + + ) ); }; diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index 162ff5baa..a820fe186 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -10,7 +10,23 @@ import API from "util/API"; import fetchData from "util/fetchData"; import CancelButton from "components/common/Button/WhiteButtons"; import SubmitButton from "components/common/Button/BlueButtons"; +import { + labelInitialData, + labelEditButtonFlagState, + labelAddButtonFlagState, + navigatorAddButtonFlagState, +} from "RecoilStore/Atoms"; +import { useRecoilValue, useSetRecoilState } from "recoil"; const LabelInput = ({ isEditor }) => { + const initialData = useRecoilValue(labelInitialData); + + // const { name, description, colors } = initialData; + //🔥애초에 여기서 가져올 수 없음. 이 값이 initial data가 되어야 함!! 제일 먼저 할일 + // 편집 클릭했을 때 보여지는 값이랑 추가 눌렀을 때 보여지는 값 달라야함 + // const { backgroundColor, textColor } = colors; + const setLabelEditBtnFlag = useSetRecoilState(labelEditButtonFlagState); + const setLabelAddBtnFlag = useSetRecoilState(labelAddButtonFlagState); + const setNavigatorAddBtnFlag = useSetRecoilState(navigatorAddButtonFlagState); const { creatorTitle, editorTitle, @@ -24,7 +40,7 @@ const LabelInput = ({ isEditor }) => { name: "레이블 이름", description: null, backgroundColor: theme.grayScale.input_background, - textColor: false, + textColor: "dark", }; const reducer = (state, { type, payload }) => { @@ -41,14 +57,15 @@ const LabelInput = ({ isEditor }) => { }; const [labelState, dispatch] = useReducer(reducer, initLabelState); + //dispatch모아서 처리하게끔 refactoring 필요 const handleClickRadioButton = event => { dispatch({ type: "textColor", payload: event.target.value }); }; const handleChangeColor = event => { //디바운스 필요(유저가 입력하고 1초 뒤에 set 하도록) + //const test = useDebounce(labelState.description, 1000); dispatch({ type: "backgroundColor", payload: event.target.value }); }; - const test = useDebounce(labelState.description, 1000); const handleTypingName = event => { if (event.target.id === "0") { @@ -58,26 +75,37 @@ const LabelInput = ({ isEditor }) => { dispatch({ type: "description", payload: event.target.value }); } }; + + const handleClose = () => { + setLabelEditBtnFlag(x => !x); + }; const handleSubmit = async () => { - const testData = { - name: "feature", - description: "새 기능", + const { name, description, backgroundColor, textColor } = labelState; + + const requestBody = { + name: name, + description: description, colors: { - backgroundColor: "#000000", - textColor: "#FFFFFF", + backgroundColor: backgroundColor, + textColor: textColor, }, }; if (isEditor) { - const res = await fetchData(API.labels(), "POST", testData); + //const res = await fetchData(API.labels(), "POST", requestBody); //PUT요청, body수정 필요 + setLabelEditBtnFlag(x => !x); } else { - const res = await fetchData(API.labels(), "POST", testData); + const res = await fetchData(API.labels(), "POST", requestBody); + setLabelAddBtnFlag(x => !x); + setNavigatorAddBtnFlag(x => !x); } }; + const getFontColor = () => { return labelState.textColor === "light" ? theme.grayScale.off_white : theme.grayScale.black; }; + const changeColor = () => { const randomColor = Math.floor(Math.random() * 16777215).toString(16); dispatch({ @@ -110,11 +138,12 @@ const LabelInput = ({ isEditor }) => { ))} - + {backgroundColorTitle} @@ -140,7 +169,12 @@ const LabelInput = ({ isEditor }) => { {isEditor && ( - + )} {isEditor ? ( { - const [LabelData, setLabelData] = useState(); - // const status = useFetch(API.labels(), "GET", setLabelData); - // console.log(LabelData, "status", status); + const [initialData, setLabelInitialData] = useRecoilState(labelInitialData); + const labelAddBtnFlag = useRecoilValue(labelAddButtonFlagState); + const labelEditBtnFlag = useRecoilValue(labelEditButtonFlagState); + const getLabelData = async () => { - const data = await fetchData(API.labels(), "GET"); - setLabelData(data); + const { labels } = await fetchData(API.labels(), "GET"); + setLabelInitialData(labels); }; useEffect(() => { @@ -22,12 +28,18 @@ const Labels = () => { return ( <> - + {labelAddBtnFlag ? : null} N개의 레이블 - - + {labelEditBtnFlag ? ( + + ) : ( + initialData && + initialData.map(data => ( + + )) + )} ); }; diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index f04d56233..68934bb66 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -7,11 +7,16 @@ import { labelButtonFlagState, milestoneButtonFlagState, milestoneAddButtonFlagState, + labelAddButtonFlagState, + navigatorAddButtonFlagState, } from "RecoilStore/Atoms"; import { useState } from "react"; const Navigator = () => { - const [isAddButton, setIsAddButton] = useState(true); + // const [isAddButton, setIsAddButton] = useState(true); + const [addButtonFlag, setAddButtonFlag] = useRecoilState( + navigatorAddButtonFlagState + ); const [milestoneFlag, setMilestoneFlag] = useRecoilState( milestoneButtonFlagState ); @@ -19,7 +24,10 @@ const Navigator = () => { const [milestoneAddBtnFlag, setMilestoneAddBtnFlag] = useRecoilState( milestoneAddButtonFlagState ); - + const [labelAddBtnFlag, setLabelAddBtnFlag] = useRecoilState( + labelAddButtonFlagState + ); + //밑에 하나로 묶어도 될 것 같음 const handleMilestoneClick = () => { setMilestoneFlag(true); setLabelFlag(false); @@ -29,14 +37,19 @@ const Navigator = () => { setLabelFlag(true); }; - const handelAddClick = () => { - if (milestoneFlag) setMilestoneAddBtnFlag(!milestoneAddBtnFlag); - else if (!milestoneFlag) setMilestoneAddBtnFlag(false); - setIsAddButton(x => !x); + //Refactoring + //리렌더 2번 일어남 + const handleClick = () => { + milestoneFlag + ? setMilestoneAddBtnFlag(!milestoneAddBtnFlag) + : setLabelAddBtnFlag(!labelAddBtnFlag); + + setAddButtonFlag(!addButtonFlag); }; return ( + {/* 버튼 그룹 카운트 자리에 데이터 길이 넣어주기 */} { isMainPage={false} /> - {isAddButton ? ( - - ) : ( + {addButtonFlag ? ( setIsAddButton(x => !x)} + clickHandler={handleClick} + /> + ) : ( + )} diff --git a/frontend/src/util/fetchData.js b/frontend/src/util/fetchData.js index 5cf659c9c..2c0c432a4 100644 --- a/frontend/src/util/fetchData.js +++ b/frontend/src/util/fetchData.js @@ -16,20 +16,16 @@ const fetchData = async (url, method, reqData) => { body: JSON.stringify(reqData), }; - // console.log("fetchData func initiated"); try { console.log("reqData:", reqData); - // console.log("option:", option); const res = await fetch(url, option); const resData = await res.json(); - // console.log("in useFetch :", resData); if (!res.ok) throw new Error(res.status); else { - // console.log("in useFetch:", resData); return await resData; } } catch (error) { - console.error("error occured"); + console.error("error occurred"); } }; From b3671ed3d15d665ef98852660d7be5afb4ac1b98 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Tue, 22 Jun 2021 11:38:28 +0900 Subject: [PATCH 60/71] =?UTF-8?q?test:=20useRef=20=EB=A1=9C=20inputData?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=A0=8C?= =?UTF-8?q?=EB=8D=94=EB=A7=81=20=EC=B5=9C=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Milestones/MilestoneInput.jsx | 75 +++++++------------ .../components/common/Button/ButtonGroup.jsx | 1 + frontend/src/components/common/Navigator.jsx | 4 +- 3 files changed, 30 insertions(+), 50 deletions(-) diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index dbb322c3c..e38088e1f 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { useState, useCallback } from "react"; +import { useState, useCallback, useRef } from "react"; import AddButton from "components/common/Button/BlueButtons"; import useFetch from "hooks/useFetch"; import API from "util/API"; @@ -28,51 +28,37 @@ const MilestoneInput = ({ milestoneAddButtonFlagState ); const [update, forceUpdate] = useRecoilState(milestoneUpdateState); - - const [titleInput, setTitleInput] = useState(title); - const [dateInput, setDateInput] = useState(dueDate); - const [descInput, setDescInput] = useState(description); + const titleRef = useRef(); + const dateRef = useRef(); + const descRef = useRef(); + const [titleInput, setTitleInput] = useState( + titleRef.current ? titleRef.current.value : "" + ); + const [dateInput, setDateInput] = useState( + dateRef.current ? dateRef.current.value : "" + ); + const [descInput, setDescInput] = useState( + descRef.current ? descRef.current.value : "" + ); const putMilestone = async () => { - await fetchData(API.milestonesId(id), "PUT", inputData); + await fetchData(API.milestonesId(id), "PUT", { + title: titleRef.current.value, + dueDate: dateRef.current.value, + description: descRef.current.value, + }); setMilestoneAddButtonFlag(false); setEditMode(false); forceUpdate(); }; - const postMilestone = async () => { - await fetchData(API.milestones(), "POST", inputData); - setMilestoneAddButtonFlag(false); - }; - - const handleTitleChange = e => { - setTitleInput(e.target.value); - setInputData({ - ...inputData, - title: e.target.value, + const postMilestone = () => { + fetchData(API.milestones(), "POST", { + title: titleRef.current.value, + dueDate: dateRef.current.value, + description: descRef.current.value, }); - }; - - const handleDateChange = e => { - setDateInput(e.target.value); - setInputData({ - ...inputData, - dueDate: e.target.value, - }); - }; - - const handleDescChange = e => { - setDescInput(e.target.value); - setInputData({ - ...inputData, - description: e.target.value, - }); - }; - - const handleSubmit = () => { - postMilestone(); setMilestoneAddButtonFlag(false); - // forceUpdate(!update); }; console.log(editMode); @@ -85,35 +71,28 @@ const MilestoneInput = ({ diff --git a/frontend/src/components/common/Button/ButtonGroup.jsx b/frontend/src/components/common/Button/ButtonGroup.jsx index b229bf9b1..ee0022cb0 100644 --- a/frontend/src/components/common/Button/ButtonGroup.jsx +++ b/frontend/src/components/common/Button/ButtonGroup.jsx @@ -16,6 +16,7 @@ const ButtonGroup = ({ labelCount, labelClickEvent, isMainPage, + handleTabClick, }) => { const milestoneFlag = useRecoilValue(milestoneButtonFlagState); const labelFlag = useRecoilValue(labelButtonFlagState); diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index f04d56233..eaf25148b 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -32,7 +32,7 @@ const Navigator = () => { const handelAddClick = () => { if (milestoneFlag) setMilestoneAddBtnFlag(!milestoneAddBtnFlag); else if (!milestoneFlag) setMilestoneAddBtnFlag(false); - setIsAddButton(x => !x); + setIsAddButton((x) => !x); }; return ( @@ -57,7 +57,7 @@ const Navigator = () => { text="취소" icon="cancel" size="m" - clickHandler={() => setIsAddButton(x => !x)} + clickHandler={handelAddClick} /> )} From bd1d5eaa555f5fc573ddfe490a9e9490ebbbc23a Mon Sep 17 00:00:00 2001 From: junzero741 Date: Tue, 22 Jun 2021 12:14:10 +0900 Subject: [PATCH 61/71] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=BC=EC=8A=A4?= =?UTF-8?q?=ED=86=A4=20=EA=B0=9C=EC=88=98=20=ED=83=AD=EA=B7=B8=EB=A3=B9?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=EC=97=90=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 5 ++ .../components/Milestones/MilestoneInput.jsx | 64 +++++++++++-------- .../src/components/Milestones/Milestones.jsx | 4 ++ .../components/common/Button/ButtonGroup.jsx | 1 - frontend/src/components/common/Navigator.jsx | 8 ++- 5 files changed, 51 insertions(+), 31 deletions(-) diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 7d3edfa82..30a196a04 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -41,3 +41,8 @@ export const milestoneUpdateState = atom({ key: "milestoneAddButtonFlagState", default: false, }); + +export const milestoneCountState = atom({ + key: "milestoneCountState", + default: 0, +}); diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index e38088e1f..2c5d35e1a 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -23,44 +23,51 @@ const MilestoneInput = ({ dueDate: dueDate, description: description, }); - const [milestoneData, setMilestoneData] = useState(); const setMilestoneAddButtonFlag = useSetRecoilState( milestoneAddButtonFlagState ); const [update, forceUpdate] = useRecoilState(milestoneUpdateState); - const titleRef = useRef(); - const dateRef = useRef(); - const descRef = useRef(); - const [titleInput, setTitleInput] = useState( - titleRef.current ? titleRef.current.value : "" - ); - const [dateInput, setDateInput] = useState( - dateRef.current ? dateRef.current.value : "" - ); - const [descInput, setDescInput] = useState( - descRef.current ? descRef.current.value : "" - ); + + const [titleInput, setTitleInput] = useState(title); + const [dateInput, setDateInput] = useState(dueDate); + const [descInput, setDescInput] = useState(description); const putMilestone = async () => { - await fetchData(API.milestonesId(id), "PUT", { - title: titleRef.current.value, - dueDate: dateRef.current.value, - description: descRef.current.value, - }); + await fetchData(API.milestonesId(id), "PUT", inputData); setMilestoneAddButtonFlag(false); setEditMode(false); forceUpdate(); }; - const postMilestone = () => { - fetchData(API.milestones(), "POST", { - title: titleRef.current.value, - dueDate: dateRef.current.value, - description: descRef.current.value, - }); + const postMilestone = async () => { + await fetchData(API.milestones(), "POST", inputData); setMilestoneAddButtonFlag(false); }; + const handleTitleChange = (e) => { + setTitleInput(e.target.value); + setInputData({ + ...inputData, + title: e.target.value, + }); + }; + + const handleDateChange = (e) => { + setDateInput(e.target.value); + setInputData({ + ...inputData, + dueDate: e.target.value, + }); + }; + + const handleDescChange = (e) => { + setDescInput(e.target.value); + setInputData({ + ...inputData, + description: e.target.value, + }); + }; + console.log(editMode); return ( @@ -71,21 +78,24 @@ const MilestoneInput = ({ { ); const [_, update] = useRecoilState(milestoneUpdateState); const [milestone, setMilestone] = useState(); + const [milestoneCount, setMilestoneCount] = + useRecoilState(milestoneCountState); const fetchMilestones = async () => { const { milestones } = await fetchData(API.milestones(), "GET"); setMilestone(milestones); + setMilestoneCount(milestones.length); }; useEffect(() => { diff --git a/frontend/src/components/common/Button/ButtonGroup.jsx b/frontend/src/components/common/Button/ButtonGroup.jsx index ee0022cb0..b229bf9b1 100644 --- a/frontend/src/components/common/Button/ButtonGroup.jsx +++ b/frontend/src/components/common/Button/ButtonGroup.jsx @@ -16,7 +16,6 @@ const ButtonGroup = ({ labelCount, labelClickEvent, isMainPage, - handleTabClick, }) => { const milestoneFlag = useRecoilValue(milestoneButtonFlagState); const labelFlag = useRecoilValue(labelButtonFlagState); diff --git a/frontend/src/components/common/Navigator.jsx b/frontend/src/components/common/Navigator.jsx index eaf25148b..eb3b742d1 100644 --- a/frontend/src/components/common/Navigator.jsx +++ b/frontend/src/components/common/Navigator.jsx @@ -2,13 +2,14 @@ import styled from "styled-components"; import ButtonGroup from "./Button/ButtonGroup"; import AddButton from "./Button/BlueButtons"; import CancelButton from "components/common/Button/WhiteButtons"; -import { useRecoilState } from "recoil"; +import { useRecoilState, useRecoilValue } from "recoil"; import { labelButtonFlagState, milestoneButtonFlagState, milestoneAddButtonFlagState, } from "RecoilStore/Atoms"; import { useState } from "react"; +import { milestoneCountState } from "RecoilStore/Atoms"; const Navigator = () => { const [isAddButton, setIsAddButton] = useState(true); @@ -19,6 +20,7 @@ const Navigator = () => { const [milestoneAddBtnFlag, setMilestoneAddBtnFlag] = useRecoilState( milestoneAddButtonFlagState ); + const milestoneCountValue = useRecoilValue(milestoneCountState); const handleMilestoneClick = () => { setMilestoneFlag(true); @@ -38,7 +40,7 @@ const Navigator = () => { return ( { text="취소" icon="cancel" size="m" - clickHandler={handelAddClick} + clickHandler={() => setIsAddButton((x) => !x)} /> )} From 3f22be037e4d65a6aaae93ff5acfc939d0ea0c51 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Tue, 22 Jun 2021 12:31:59 +0900 Subject: [PATCH 62/71] =?UTF-8?q?chore:=20=EC=95=88=EC=93=B0=EB=8A=94=20?= =?UTF-8?q?=EC=BD=94=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 --- frontend/src/components/Milestones/MilestoneInput.jsx | 3 +-- frontend/src/components/Milestones/Milestones.jsx | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/frontend/src/components/Milestones/MilestoneInput.jsx b/frontend/src/components/Milestones/MilestoneInput.jsx index 2c5d35e1a..b621987c6 100644 --- a/frontend/src/components/Milestones/MilestoneInput.jsx +++ b/frontend/src/components/Milestones/MilestoneInput.jsx @@ -1,7 +1,6 @@ import styled from "styled-components"; -import { useState, useCallback, useRef } from "react"; +import { useState } from "react"; import AddButton from "components/common/Button/BlueButtons"; -import useFetch from "hooks/useFetch"; import API from "util/API"; import { useSetRecoilState, useRecoilState } from "recoil"; import { diff --git a/frontend/src/components/Milestones/Milestones.jsx b/frontend/src/components/Milestones/Milestones.jsx index efabcb0c3..531d7614c 100644 --- a/frontend/src/components/Milestones/Milestones.jsx +++ b/frontend/src/components/Milestones/Milestones.jsx @@ -15,7 +15,6 @@ const Milestones = () => { const [milestoneAddBtn, setMilestoneAddBtn] = useRecoilState( milestoneAddButtonFlagState ); - const [_, update] = useRecoilState(milestoneUpdateState); const [milestone, setMilestone] = useState(); const [milestoneCount, setMilestoneCount] = useRecoilState(milestoneCountState); From 344f740be0a9cecc0b8e9febe91aa388891ced96 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Tue, 22 Jun 2021 15:07:54 +0900 Subject: [PATCH 63/71] =?UTF-8?q?feat:=20POST,=20DELETE=20request=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelCard.jsx | 14 +++- frontend/src/components/Labels/LabelInput.jsx | 79 +++++++++++-------- frontend/src/components/Labels/Labels.jsx | 20 +++-- frontend/src/data.js | 4 +- frontend/src/util/fetchData.js | 2 +- 5 files changed, 71 insertions(+), 48 deletions(-) diff --git a/frontend/src/components/Labels/LabelCard.jsx b/frontend/src/components/Labels/LabelCard.jsx index 041807018..0c72aabac 100644 --- a/frontend/src/components/Labels/LabelCard.jsx +++ b/frontend/src/components/Labels/LabelCard.jsx @@ -7,16 +7,24 @@ import theme from "styles/theme"; import { CenterJcAi, CenterAi } from "styles/StyledLayout "; import { labelInitialData, labelEditButtonFlagState } from "RecoilStore/Atoms"; import { useRecoilValue, useSetRecoilState } from "recoil"; - +import API from "util/API"; +import fetchData from "util/fetchData"; const LabelCard = ({ initialData }) => { - const { name, description, colors } = initialData; + const { id, name, description, colors } = initialData; const { backgroundColor, textColor } = colors; const setLabelEditBtnFlag = useSetRecoilState(labelEditButtonFlagState); + const setLabelInitialData = useSetRecoilState(labelInitialData); const handleEditButton = () => { setLabelEditBtnFlag(x => !x); }; - const handleDeleteButton = () => {}; + const handleDeleteButton = async () => { + console.log("delete"); + console.log("id!!", id); + await fetchData(API.labelsId(id), "DELETE"); + const { labels } = await fetchData(API.labels(), "GET"); + setLabelInitialData(labels); + }; return ( initialData && ( diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index a820fe186..21de45d9d 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -16,14 +16,10 @@ import { labelAddButtonFlagState, navigatorAddButtonFlagState, } from "RecoilStore/Atoms"; -import { useRecoilValue, useSetRecoilState } from "recoil"; -const LabelInput = ({ isEditor }) => { - const initialData = useRecoilValue(labelInitialData); +import { useSetRecoilState, useRecoilState } from "recoil"; - // const { name, description, colors } = initialData; - //🔥애초에 여기서 가져올 수 없음. 이 값이 initial data가 되어야 함!! 제일 먼저 할일 - // 편집 클릭했을 때 보여지는 값이랑 추가 눌렀을 때 보여지는 값 달라야함 - // const { backgroundColor, textColor } = colors; +const LabelInput = ({ initialData, isEditor }) => { + const setLabelInitialData = useSetRecoilState(labelInitialData); const setLabelEditBtnFlag = useSetRecoilState(labelEditButtonFlagState); const setLabelAddBtnFlag = useSetRecoilState(labelAddButtonFlagState); const setNavigatorAddBtnFlag = useSetRecoilState(navigatorAddButtonFlagState); @@ -35,12 +31,15 @@ const LabelInput = ({ isEditor }) => { textColorTitles, buttons, } = labelData; + const { id, name, description, colors } = initialData; + const { backgroundColor, textColor } = colors; + console.log("input", initialData.id); const initLabelState = { - name: "레이블 이름", - description: null, + name: name, + description: description, backgroundColor: theme.grayScale.input_background, - textColor: "dark", + textColor: "#000000", }; const reducer = (state, { type, payload }) => { @@ -59,7 +58,9 @@ const LabelInput = ({ isEditor }) => { //dispatch모아서 처리하게끔 refactoring 필요 const handleClickRadioButton = event => { - dispatch({ type: "textColor", payload: event.target.value }); + const currentTextColor = + event.target.value === + dispatch({ type: "textColor", payload: event.target.value }); }; const handleChangeColor = event => { //디바운스 필요(유저가 입력하고 1초 뒤에 set 하도록) @@ -79,8 +80,9 @@ const LabelInput = ({ isEditor }) => { const handleClose = () => { setLabelEditBtnFlag(x => !x); }; + const handleSubmit = async () => { - const { name, description, backgroundColor, textColor } = labelState; + const { id, name, description, backgroundColor, textColor } = labelState; const requestBody = { name: name, @@ -97,15 +99,11 @@ const LabelInput = ({ isEditor }) => { const res = await fetchData(API.labels(), "POST", requestBody); setLabelAddBtnFlag(x => !x); setNavigatorAddBtnFlag(x => !x); + const { labels } = await fetchData(API.labels(), "GET"); + setLabelInitialData(labels); } }; - const getFontColor = () => { - return labelState.textColor === "light" - ? theme.grayScale.off_white - : theme.grayScale.black; - }; - const changeColor = () => { const randomColor = Math.floor(Math.random() * 16777215).toString(16); dispatch({ @@ -113,30 +111,43 @@ const LabelInput = ({ isEditor }) => { payload: `#${randomColor}`, }); }; - + console.log("name", name); return ( {isEditor ? editorTitle : creatorTitle} - + { + + } - {inputTitles.map((title, idx) => ( - - {title} - - - ))} + {/* 타이틀 부분 나눠서 디스크립션 부분은 온 체인지 풀기 */} + + + {inputTitles[0]} + + + + {inputTitles[1]} + + + {backgroundColorTitle} diff --git a/frontend/src/components/Labels/Labels.jsx b/frontend/src/components/Labels/Labels.jsx index 243d0e181..f78acff03 100644 --- a/frontend/src/components/Labels/Labels.jsx +++ b/frontend/src/components/Labels/Labels.jsx @@ -32,14 +32,18 @@ const Labels = () => { N개의 레이블 - {labelEditBtnFlag ? ( - - ) : ( - initialData && - initialData.map(data => ( - - )) - )} + {initialData && + initialData.map(data => + labelEditBtnFlag ? ( + + ) : ( + + ) + )} ); }; diff --git a/frontend/src/data.js b/frontend/src/data.js index d1f9c6409..0134a1215 100644 --- a/frontend/src/data.js +++ b/frontend/src/data.js @@ -44,8 +44,8 @@ export const labelData = { cancel: "취소", submit: "완료", radio: [ - { value: "light", text: "밝은 색" }, - { value: "dark", text: "어두운 색" }, + { value: "#FEFEFE", text: "밝은 색" }, + { value: "#000000", text: "어두운 색" }, ], }, }; diff --git a/frontend/src/util/fetchData.js b/frontend/src/util/fetchData.js index 2c0c432a4..ff76a292f 100644 --- a/frontend/src/util/fetchData.js +++ b/frontend/src/util/fetchData.js @@ -1,6 +1,6 @@ const fetchData = async (url, method, reqData) => { const option = - method === "GET" + (method === "GET") | "DELETE" ? { headers: { "Content-Type": "application/json", From f9cfff6b6226fe750cf238434ee0ffc2c1c24d78 Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Tue, 22 Jun 2021 16:34:12 +0900 Subject: [PATCH 64/71] =?UTF-8?q?style:=20=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 7d5299b83..0518b54de 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -59,9 +59,8 @@ export const labelEditButtonFlagState = atom({ export const navigatorAddButtonFlagState = atom({ key: "navigatorAddButtonFlagState", default: false, - +}); export const milestoneCountState = atom({ key: "milestoneCountState", default: 0, - }); From 2b40d054c1172874e0deebd7fde4e8d6f810c35b Mon Sep 17 00:00:00 2001 From: Dami Kim Date: Tue, 22 Jun 2021 17:39:06 +0900 Subject: [PATCH 65/71] =?UTF-8?q?WIP:=20=EB=B2=84=EA=B7=B8=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=EC=A4=91=20(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Labels/LabelCard.jsx | 17 ++++--- frontend/src/components/Labels/LabelInput.jsx | 49 ++++++++++--------- frontend/src/components/Labels/Labels.jsx | 16 ++---- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/frontend/src/components/Labels/LabelCard.jsx b/frontend/src/components/Labels/LabelCard.jsx index 0c72aabac..d78d3a3d3 100644 --- a/frontend/src/components/Labels/LabelCard.jsx +++ b/frontend/src/components/Labels/LabelCard.jsx @@ -6,14 +6,17 @@ import { ReactComponent as TrashIcon } from "images/trash.svg"; import theme from "styles/theme"; import { CenterJcAi, CenterAi } from "styles/StyledLayout "; import { labelInitialData, labelEditButtonFlagState } from "RecoilStore/Atoms"; -import { useRecoilValue, useSetRecoilState } from "recoil"; +import { useRecoilValue, useSetRecoilState, useRecoilState } from "recoil"; import API from "util/API"; import fetchData from "util/fetchData"; +import LabelInput from "./LabelInput"; const LabelCard = ({ initialData }) => { const { id, name, description, colors } = initialData; const { backgroundColor, textColor } = colors; - const setLabelEditBtnFlag = useSetRecoilState(labelEditButtonFlagState); + const [editBtnFlag, setLabelEditBtnFlag] = useRecoilState( + labelEditButtonFlagState + ); const setLabelInitialData = useSetRecoilState(labelInitialData); const handleEditButton = () => { setLabelEditBtnFlag(x => !x); @@ -27,8 +30,10 @@ const LabelCard = ({ initialData }) => { }; return ( - initialData && ( - <> + <> + {editBtnFlag ? ( + + ) : ( { - - ) + )} + ); }; diff --git a/frontend/src/components/Labels/LabelInput.jsx b/frontend/src/components/Labels/LabelInput.jsx index 21de45d9d..cc2a23433 100644 --- a/frontend/src/components/Labels/LabelInput.jsx +++ b/frontend/src/components/Labels/LabelInput.jsx @@ -5,7 +5,6 @@ import { useEffect, useReducer } from "react"; import LabelBadge from "components/common/LabelBadge"; import theme from "styles/theme"; import { labelData } from "data"; -import useDebounce from "hooks/useDebounce"; import API from "util/API"; import fetchData from "util/fetchData"; import CancelButton from "components/common/Button/WhiteButtons"; @@ -16,13 +15,17 @@ import { labelAddButtonFlagState, navigatorAddButtonFlagState, } from "RecoilStore/Atoms"; -import { useSetRecoilState, useRecoilState } from "recoil"; -const LabelInput = ({ initialData, isEditor }) => { +import { useSetRecoilState, useRecoilState, useRecoilValue } from "recoil"; + +const LabelInput = ({ initialData }) => { const setLabelInitialData = useSetRecoilState(labelInitialData); - const setLabelEditBtnFlag = useSetRecoilState(labelEditButtonFlagState); + const [editBtnFlag, setLabelEditBtnFlag] = useRecoilState( + labelEditButtonFlagState + ); const setLabelAddBtnFlag = useSetRecoilState(labelAddButtonFlagState); const setNavigatorAddBtnFlag = useSetRecoilState(navigatorAddButtonFlagState); + const { creatorTitle, editorTitle, @@ -31,13 +34,15 @@ const LabelInput = ({ initialData, isEditor }) => { textColorTitles, buttons, } = labelData; + const { id, name, description, colors } = initialData; - const { backgroundColor, textColor } = colors; - console.log("input", initialData.id); + // const { backgroundColor, textColor } = colors; + const backgroundColor = "#000"; + const textColor = "#000"; const initLabelState = { - name: name, - description: description, + name: "test", + description: "tst", backgroundColor: theme.grayScale.input_background, textColor: "#000000", }; @@ -92,7 +97,7 @@ const LabelInput = ({ initialData, isEditor }) => { textColor: textColor, }, }; - if (isEditor) { + if (editBtnFlag) { //const res = await fetchData(API.labels(), "POST", requestBody); //PUT요청, body수정 필요 setLabelEditBtnFlag(x => !x); } else { @@ -111,19 +116,17 @@ const LabelInput = ({ initialData, isEditor }) => { payload: `#${randomColor}`, }); }; - console.log("name", name); + return ( - - {isEditor ? editorTitle : creatorTitle} + + {editBtnFlag ? editorTitle : creatorTitle} { } @@ -136,7 +139,7 @@ const LabelInput = ({ initialData, isEditor }) => { @@ -144,7 +147,7 @@ const LabelInput = ({ initialData, isEditor }) => { @@ -179,7 +182,7 @@ const LabelInput = ({ initialData, isEditor }) => { - {isEditor && ( + {editBtnFlag && ( { clickHandler={handleClose} /> )} - {isEditor ? ( + {editBtnFlag ? ( theme.grayScale.off_white}; border: 1px solid ${({ theme }) => theme.grayScale.line}; - border-radius: ${props => (props.isEditor ? "none" : "16px")}; - margin-bottom: ${props => (props.isEditor ? 0 : "2%")}; + border-radius: ${props => (props.editBtnFlag ? "none" : "16px")}; + margin-bottom: ${props => (props.editBtnFlag ? 0 : "2%")}; `; const MainLayout = styled.div` diff --git a/frontend/src/components/Labels/Labels.jsx b/frontend/src/components/Labels/Labels.jsx index f78acff03..44de0f291 100644 --- a/frontend/src/components/Labels/Labels.jsx +++ b/frontend/src/components/Labels/Labels.jsx @@ -28,22 +28,14 @@ const Labels = () => { return ( <> - {labelAddBtnFlag ? : null} + {labelAddBtnFlag ? : <>} N개의 레이블 {initialData && - initialData.map(data => - labelEditBtnFlag ? ( - - ) : ( - - ) - )} + initialData.map(data => ( + + ))} ); }; From 332a6e228dd593972fd0e113c79ede996d586712 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Tue, 22 Jun 2021 18:06:07 +0900 Subject: [PATCH 66/71] =?UTF-8?q?WIP:=20=EC=83=88=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20HTML=20=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/RecoilStore/Atoms.jsx | 2 +- .../src/components/NewIssues/NewIssueForm.jsx | 44 ++++++++++++++++--- .../components/NewIssues/NewIssueInput.jsx | 13 ------ .../src/components/common/CommentInput.jsx | 31 ++++++++++++- frontend/src/util/fetchData.js | 1 + 5 files changed, 70 insertions(+), 21 deletions(-) delete mode 100644 frontend/src/components/NewIssues/NewIssueInput.jsx diff --git a/frontend/src/RecoilStore/Atoms.jsx b/frontend/src/RecoilStore/Atoms.jsx index 7d5299b83..52c71deb9 100644 --- a/frontend/src/RecoilStore/Atoms.jsx +++ b/frontend/src/RecoilStore/Atoms.jsx @@ -59,9 +59,9 @@ export const labelEditButtonFlagState = atom({ export const navigatorAddButtonFlagState = atom({ key: "navigatorAddButtonFlagState", default: false, +}); export const milestoneCountState = atom({ key: "milestoneCountState", default: 0, - }); diff --git a/frontend/src/components/NewIssues/NewIssueForm.jsx b/frontend/src/components/NewIssues/NewIssueForm.jsx index 4aaea55d7..019b30ade 100644 --- a/frontend/src/components/NewIssues/NewIssueForm.jsx +++ b/frontend/src/components/NewIssues/NewIssueForm.jsx @@ -1,18 +1,30 @@ +import { Link } from "react-router-dom"; import styled from "styled-components"; -import NewIssueInput from "./NewIssueInput"; import IssueCategoryList from "components/common/IssueCategoryList"; +import CommentInput from "components/common/CommentInput"; const NewIssueForm = () => { + const handleSubmit = () => { + console.log("작성완료"); + }; + return ( <> - + + + + + + {/* 스타일 코드 작성시 이부분 button 컴포넌트 적용 필요 */} - - + + + + ); @@ -21,13 +33,33 @@ const NewIssueForm = () => { export default NewIssueForm; const Wrapper = styled.div` - display: flex; - padding: ${({ theme }) => `${theme.fontSizes.titleSize} 0`}; + display: grid; + grid-template-columns: 3fr 1fr; + padding: ${({ theme }) => `${theme.fontSizes.xxxl} 0`}; border-bottom: 1px solid ${({ theme }) => theme.grayScale.line}; `; +const ContentsWrapper = styled.div` + width: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; +`; + const ButtonWrapper = styled.div` display: flex; justify-content: flex-end; padding: ${({ theme }) => `${theme.fontSizes.titleSize} 0`}; `; + +const InputTitleWrapper = styled.div` + padding: 1%; + margin-bottom: ${({ theme }) => theme.paddings.xxl}; + border-radius: 14px; + background-color: ${({ theme }) => theme.grayScale.input_background}; +`; +const Input = styled.input` + border: none; + width: 100%; + background-color: ${({ theme }) => theme.grayScale.input_background}; +`; diff --git a/frontend/src/components/NewIssues/NewIssueInput.jsx b/frontend/src/components/NewIssues/NewIssueInput.jsx deleted file mode 100644 index 91790d9c5..000000000 --- a/frontend/src/components/NewIssues/NewIssueInput.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import CommentInput from "components/common/CommentInput"; -import IssueCategoryList from "components/common/IssueCategoryList"; - -const NewIssueInput = () => { - return ( -
-
이슈 제목입력
- -
- ); -}; - -export default NewIssueInput; diff --git a/frontend/src/components/common/CommentInput.jsx b/frontend/src/components/common/CommentInput.jsx index 9394fe070..e4092d0f3 100644 --- a/frontend/src/components/common/CommentInput.jsx +++ b/frontend/src/components/common/CommentInput.jsx @@ -1,5 +1,34 @@ +import styled from "styled-components"; +import { ReactComponent as Clip } from "images/paperclip.svg"; + const CommentInput = () => { - return
이슈 코멘트 입력
; + return ( + + +