From 6eeaa84b4b56f3db22ad5e8b9fef2c10ed77614d Mon Sep 17 00:00:00 2001 From: codeisneverodd Date: Wed, 20 Jul 2022 19:41:26 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20input=20=EC=9E=85=EB=A0=A5=EC=8B=9C?= =?UTF-8?q?=20=EA=B2=80=EC=83=89=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=EA=B0=80=20?= =?UTF-8?q?=EB=B3=B4=EC=9D=B4=EA=B3=A0,=20=EC=84=A0=ED=83=9D=20=EC=8B=9C?= =?UTF-8?q?=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=EA=B0=80=20=EB=B3=B4=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solutionReportPage/SolutionReport.js | 51 +++++++++---------- src/style/styledComponents.js | 4 +- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/src/pages/solutionReportPage/SolutionReport.js b/src/pages/solutionReportPage/SolutionReport.js index ab6b177..fb7e08e 100644 --- a/src/pages/solutionReportPage/SolutionReport.js +++ b/src/pages/solutionReportPage/SolutionReport.js @@ -5,6 +5,9 @@ import { InputLabel, MainContetnWrapper, OtherReportBtn, + QuestionBtn, + QuestionItem, + QuestionList, StepByStepInputItem, SubmitBtn, TextArea, @@ -21,6 +24,7 @@ export default function SolutionReport() { const [submitted, setSubmitted] = useState(false); const [questionName, setQuestionName] = useState(""); const [detailContent, setDetailContent] = useState(""); + const [isQuestionListVisible, setIsQuestionListVisible] = useState(true); const [searchParams, setSearchParams] = useSearchParams(); const userInfo = useUserProfile(); const { isLoggedIn, requestLogin } = useUserLogin(); @@ -43,8 +47,12 @@ export default function SolutionReport() { function handleQuestionNameInput(e) { setQuestionName(e.target.value); + if (!isQuestionListVisible) setIsQuestionListVisible(true); + } + function handleQuestionClick(e) { + setIsQuestionListVisible(false); + setQuestionName(e.target.dataset.value); } - function handleDetailContentInput(e) { setDetailContent(e.target.value); } @@ -72,34 +80,23 @@ export default function SolutionReport() { id="questionNameInput" placeholder="문제 이름을 검색하세요." defaultValue={questionName} + value={questionName} onInput={handleQuestionNameInput} /> - {/**/} - {/* */} - {/* 1번문제*/} - {/* */} - {/* */} - {/* 2번문제*/} - {/* */} - {/* */} - {/* 3번문제*/} - {/* */} - {/* */} - {/* 4번문제*/} - {/* */} - {/* */} - {/* 5번문제*/} - {/* */} - {/* */} - {/* 6번문제*/} - {/* */} - {/* */} - {/* 7번문제*/} - {/* */} - {/* */} - {/* 8번문제*/} - {/* */} - {/**/} + {isQuestionListVisible && ( + + {[1, 2, 3, 4, 5].map((value) => ( + + + {value}번 문제 + + + ))} + + )} {/*isDetailContentVisible &&*/} diff --git a/src/style/styledComponents.js b/src/style/styledComponents.js index d5048ee..3970d27 100644 --- a/src/style/styledComponents.js +++ b/src/style/styledComponents.js @@ -49,7 +49,7 @@ export const TextInput = styled.input` `; export const QuestionList = styled.ul` - // display: none; + //display: none; position: absolute; top: 20rem; left: 0; @@ -62,7 +62,7 @@ export const QuestionList = styled.ul` export const QuestionItem = styled.li``; -export const QuestionBtn = styled.button` +export const QuestionBtn = styled.div` width: 100%; height: 9rem; text-align: left; From aa1618413bf57fb31570cf56016614398d224501 Mon Sep 17 00:00:00 2001 From: codeisneverodd Date: Wed, 20 Jul 2022 19:58:56 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20QuestionList=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=ED=99=94=20=EB=B0=8F=20ErrorReport=20?= =?UTF-8?q?=EC=9D=98=20QuestionList=20=EC=A3=BC=EC=84=9D=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/errorReportPage/ErrorReport.js | 76 +++++++++---------- .../solutionReportPage/SolutionReport.js | 41 +--------- .../components/QuestionList.js | 71 +++++++++++++++++ src/style/styledComponents.js | 30 -------- 4 files changed, 111 insertions(+), 107 deletions(-) create mode 100644 src/pages/solutionReportPage/components/QuestionList.js diff --git a/src/pages/errorReportPage/ErrorReport.js b/src/pages/errorReportPage/ErrorReport.js index 4fba4b6..33ca37b 100644 --- a/src/pages/errorReportPage/ErrorReport.js +++ b/src/pages/errorReportPage/ErrorReport.js @@ -2,17 +2,13 @@ import { useState } from "react"; import styled from "styled-components"; import Header from "../../components/Header"; import { - ThanksMsg, - OtherReportBtn, + InputLabel, MainContetnWrapper, + OtherReportBtn, StepByStepInputItem, - InputLabel, - TextInput, - QuestionList, - QuestionItem, - QuestionBtn, - TextArea, SubmitBtn, + TextArea, + ThanksMsg, } from "../../style/styledComponents"; export default function ErrorReport() { @@ -110,38 +106,38 @@ export default function ErrorReport() { {isQuestionNameVisible && ( 문제 이름 - - - - 1번문제 - - - 2번문제 - - - 3번문제 - - - 4번문제 - - - 5번문제 - - - 6번문제 - - - 7번문제 - - - 8번문제 - - + {/**/} + {/**/} + {/* */} + {/* 1번문제*/} + {/* */} + {/* */} + {/* 2번문제*/} + {/* */} + {/* */} + {/* 3번문제*/} + {/* */} + {/* */} + {/* 4번문제*/} + {/* */} + {/* */} + {/* 5번문제*/} + {/* */} + {/* */} + {/* 6번문제*/} + {/* */} + {/* */} + {/* 7번문제*/} + {/* */} + {/* */} + {/* 8번문제*/} + {/* */} + {/**/} )} diff --git a/src/pages/solutionReportPage/SolutionReport.js b/src/pages/solutionReportPage/SolutionReport.js index fb7e08e..b9c0ebb 100644 --- a/src/pages/solutionReportPage/SolutionReport.js +++ b/src/pages/solutionReportPage/SolutionReport.js @@ -5,13 +5,9 @@ import { InputLabel, MainContetnWrapper, OtherReportBtn, - QuestionBtn, - QuestionItem, - QuestionList, StepByStepInputItem, SubmitBtn, TextArea, - TextInput, ThanksMsg, } from "../../style/styledComponents"; import gitHubLogoSrc from "../../images/github-logo-white.png"; @@ -19,12 +15,11 @@ import { useSearchParams } from "react-router-dom"; import { LOGIN_URL } from "./utils/gitHubLogin"; import useUserProfile from "../../hooks/user/useUserProfile"; import useUserLogin from "../../hooks/user/useUserLogin"; +import QuestionList from "./components/QuestionList"; export default function SolutionReport() { const [submitted, setSubmitted] = useState(false); - const [questionName, setQuestionName] = useState(""); const [detailContent, setDetailContent] = useState(""); - const [isQuestionListVisible, setIsQuestionListVisible] = useState(true); const [searchParams, setSearchParams] = useSearchParams(); const userInfo = useUserProfile(); const { isLoggedIn, requestLogin } = useUserLogin(); @@ -36,23 +31,15 @@ export default function SolutionReport() { } }, [searchParams]); const handleGitHubLogin = async () => {}; - const isDetailContentVisible = questionName !== ""; + // const isDetailContentVisible = questionName !== ""; const isSubmitBtnDisabled = detailContent === ""; function handleOtherSolutionBtnClick() { setSubmitted(false); - setQuestionName(""); + // setQuestionName(""); setDetailContent(""); } - function handleQuestionNameInput(e) { - setQuestionName(e.target.value); - if (!isQuestionListVisible) setIsQuestionListVisible(true); - } - function handleQuestionClick(e) { - setIsQuestionListVisible(false); - setQuestionName(e.target.dataset.value); - } function handleDetailContentInput(e) { setDetailContent(e.target.value); } @@ -76,27 +63,7 @@ export default function SolutionReport() { 문제 이름 - - {isQuestionListVisible && ( - - {[1, 2, 3, 4, 5].map((value) => ( - - - {value}번 문제 - - - ))} - - )} + {/*isDetailContentVisible &&*/} diff --git a/src/pages/solutionReportPage/components/QuestionList.js b/src/pages/solutionReportPage/components/QuestionList.js new file mode 100644 index 0000000..6b773dd --- /dev/null +++ b/src/pages/solutionReportPage/components/QuestionList.js @@ -0,0 +1,71 @@ +import styled from "styled-components"; +import { TextInput } from "../../../style/styledComponents"; +import { useState } from "react"; + +const QuestionList = () => { + const [isQuestionListVisible, setIsQuestionListVisible] = useState(false); + const [questionName, setQuestionName] = useState(""); + function handleQuestionClick(e) { + setIsQuestionListVisible(false); + setQuestionName(e.target.dataset.value); + } + function handleQuestionNameInput(e) { + setQuestionName(e.target.value); + if (!isQuestionListVisible) setIsQuestionListVisible(true); + } + + return ( + <> + + {isQuestionListVisible && ( + + {[1, 2, 3, 4, 5].map((value) => ( + + + {value}번 문제 + + + ))} + + )} + + ); +}; +export default QuestionList; +export const Wrapper = styled.ul` + //display: none; + position: absolute; + top: 20rem; + left: 0; + width: 100%; + height: 33.2rem; + background-color: ${(props) => props.theme.searchBg}; + overflow: scroll; + z-index: 10; +`; +export const QuestionItem = styled.li``; + +export const QuestionBtn = styled.div` + width: 100%; + height: 9rem; + text-align: left; + line-height: 9rem; + text-indent: 2rem; + background-color: transparent; + font-size: 3.1rem; + color: ${(props) => props.theme.basicWhite}; + border-bottom: 1px solid ${(props) => props.theme.notSelectedTab}; + cursor: pointer; + &:hover { + background-color: ${(props) => props.theme.programmersBlue}; + } +`; diff --git a/src/style/styledComponents.js b/src/style/styledComponents.js index 3970d27..e154534 100644 --- a/src/style/styledComponents.js +++ b/src/style/styledComponents.js @@ -48,36 +48,6 @@ export const TextInput = styled.input` border: 0; `; -export const QuestionList = styled.ul` - //display: none; - position: absolute; - top: 20rem; - left: 0; - width: 100%; - height: 33.2rem; - background-color: ${(props) => props.theme.searchBg}; - overflow: scroll; - z-index: 10; -`; - -export const QuestionItem = styled.li``; - -export const QuestionBtn = styled.div` - width: 100%; - height: 9rem; - text-align: left; - line-height: 9rem; - text-indent: 2rem; - background-color: transparent; - font-size: 3.1rem; - color: ${(props) => props.theme.basicWhite}; - border-bottom: 1px solid ${(props) => props.theme.notSelectedTab}; - cursor: pointer; - &:hover { - background-color: ${(props) => props.theme.programmersBlue}; - } -`; - export const SubmitBtn = styled.button` width: 100%; height: 13rem; From fa4dfc15c859ef550c20973e1e87949520f82cc5 Mon Sep 17 00:00:00 2001 From: codeisneverodd Date: Thu, 21 Jul 2022 10:27:57 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20solution=20fetch=20=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/solutionList.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/apis/solutionList.js diff --git a/src/apis/solutionList.js b/src/apis/solutionList.js new file mode 100644 index 0000000..8fc8011 --- /dev/null +++ b/src/apis/solutionList.js @@ -0,0 +1,7 @@ +const GET_SOLUTION_LIST_BASE_URL = `https://api.github.com/repos/codeisneverodd/programmers-coding-test/contents/`; + +export const requestSolutionListByLevelAPI = async (level) => { + const url = GET_SOLUTION_LIST_BASE_URL + `level-${level}`; + const response = await fetch(url); + return await response.json(); +}; From a21ba90182b17738aba6c11461091ed9da4bdc2b Mon Sep 17 00:00:00 2001 From: codeisneverodd Date: Thu, 21 Jul 2022 10:28:14 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20=ED=95=9C=EA=B8=80=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=EC=9D=84=20=EC=9C=84=ED=95=9C=20=ED=95=A8=EC=88=98=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 --- src/components/utils/createFuzzyMatcher.js | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/components/utils/createFuzzyMatcher.js diff --git a/src/components/utils/createFuzzyMatcher.js b/src/components/utils/createFuzzyMatcher.js new file mode 100644 index 0000000..13a6f83 --- /dev/null +++ b/src/components/utils/createFuzzyMatcher.js @@ -0,0 +1,38 @@ +const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + +const ch2pattern = (ch) => { + const offset = 44032; + if (/[가-힣]/.test(ch)) { + const chCode = ch.charCodeAt(0) - offset; + if (chCode % 28 > 0) { + return ch; + } + const begin = Math.floor(chCode / 28) * 28 + offset; + const end = begin + 27; + return `[\\u${begin.toString(16)}-\\u${end.toString(16)}]`; + } + if (/[ㄱ-ㅎ]/.test(ch)) { + const con2syl = { + ㄱ: "가".charCodeAt(0), + ㄲ: "까".charCodeAt(0), + ㄴ: "나".charCodeAt(0), + ㄷ: "다".charCodeAt(0), + ㄸ: "따".charCodeAt(0), + ㄹ: "라".charCodeAt(0), + ㅁ: "마".charCodeAt(0), + ㅂ: "바".charCodeAt(0), + ㅃ: "빠".charCodeAt(0), + ㅅ: "사".charCodeAt(0), + }; + const begin = + con2syl[ch] || (ch.charCodeAt(0) - 12613) * 588 + con2syl["ㅅ"]; + const end = begin + 587; + return `[${ch}\\u${begin.toString(16)}-\\u${end.toString(16)}]`; + } + return escapeRegExp(ch); +}; + +export const createFuzzyMatcher = (input) => { + const pattern = input.split("").map(ch2pattern).join(".*?"); + return new RegExp(pattern); +}; From 886bf2c468791a36af1ffe825d359427bdcded1a Mon Sep 17 00:00:00 2001 From: codeisneverodd Date: Thu, 21 Jul 2022 10:28:50 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20=ED=95=B4=EC=84=A4=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=A0=84=EC=97=AD=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20localStor?= =?UTF-8?q?ageEffect=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/state/solutionList.js | 9 ++++++++ src/state/user.js | 4 ++-- src/state/utils/sessionStorageEffect.js | 14 ------------ src/state/utils/storageEffect.js | 29 +++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 src/state/solutionList.js delete mode 100644 src/state/utils/sessionStorageEffect.js create mode 100644 src/state/utils/storageEffect.js diff --git a/src/state/solutionList.js b/src/state/solutionList.js new file mode 100644 index 0000000..f60839b --- /dev/null +++ b/src/state/solutionList.js @@ -0,0 +1,9 @@ +import { atom } from "recoil"; +import { localStorageEffect } from "./utils/storageEffect"; + +const solutionListState = atom({ + key: "solutionListState", + default: [], + effects: [localStorageEffect("solutionListState")], +}); +export default solutionListState; diff --git a/src/state/user.js b/src/state/user.js index 71fd64d..44f8737 100644 --- a/src/state/user.js +++ b/src/state/user.js @@ -1,10 +1,10 @@ import { atom } from "recoil"; -import { sessionStorageEffect } from "./utils/sessionStorageEffect"; +import { storageEffect } from "./utils/storageEffect"; const userState = atom({ key: "userState", default: {}, - effects: [sessionStorageEffect("userState")], + effects: [storageEffect("userState")], }); export default userState; diff --git a/src/state/utils/sessionStorageEffect.js b/src/state/utils/sessionStorageEffect.js deleted file mode 100644 index f994c05..0000000 --- a/src/state/utils/sessionStorageEffect.js +++ /dev/null @@ -1,14 +0,0 @@ -export const sessionStorageEffect = - (key) => - ({ setSelf, onSet }) => { - const savedValue = sessionStorage.getItem(key); - if (savedValue != null) { - setSelf(JSON.parse(savedValue)); - } - - onSet((newValue, _, isReset) => { - isReset - ? sessionStorage.removeItem(key) - : sessionStorage.setItem(key, JSON.stringify(newValue)); - }); - }; diff --git a/src/state/utils/storageEffect.js b/src/state/utils/storageEffect.js new file mode 100644 index 0000000..5e53f19 --- /dev/null +++ b/src/state/utils/storageEffect.js @@ -0,0 +1,29 @@ +export const localStorageEffect = + (key) => + ({ setSelf, onSet }) => { + const savedValue = localStorage.getItem(key); + if (savedValue != null) { + setSelf(JSON.parse(savedValue)); + } + + onSet((newValue, _, isReset) => { + isReset + ? localStorage.removeItem(key) + : localStorage.setItem(key, JSON.stringify(newValue)); + }); + }; + +export const storageEffect = + (key) => + ({ setSelf, onSet }) => { + const savedValue = sessionStorage.getItem(key); + if (savedValue != null) { + setSelf(JSON.parse(savedValue)); + } + + onSet((newValue, _, isReset) => { + isReset + ? sessionStorage.removeItem(key) + : sessionStorage.setItem(key, JSON.stringify(newValue)); + }); + }; From c7bcdd6fe55688bf05cd0a3449264b94b2e0775a Mon Sep 17 00:00:00 2001 From: codeisneverodd Date: Thu, 21 Jul 2022 10:29:08 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20solutionList=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=BB=A4?= =?UTF-8?q?=EC=8A=A4=ED=85=80=20=ED=9B=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solutionList/useFetchSolutionList.js | 35 +++++++++++++++++++ src/hooks/solutionList/useSetSolutionList.js | 7 ++++ .../solutionList/useSolutionListValue.js | 7 ++++ 3 files changed, 49 insertions(+) create mode 100644 src/hooks/solutionList/useFetchSolutionList.js create mode 100644 src/hooks/solutionList/useSetSolutionList.js create mode 100644 src/hooks/solutionList/useSolutionListValue.js diff --git a/src/hooks/solutionList/useFetchSolutionList.js b/src/hooks/solutionList/useFetchSolutionList.js new file mode 100644 index 0000000..a013f64 --- /dev/null +++ b/src/hooks/solutionList/useFetchSolutionList.js @@ -0,0 +1,35 @@ +import useSetSolutionList from "./useSetSolutionList"; +import { requestSolutionListByLevelAPI } from "../../apis/solutionList"; + +const useFetchSolutionList = () => { + const setSolutionList = useSetSolutionList(); + const POSSIBLE_LEVEL = [1, 2, 3, 4, 5]; + + const fetchSolutionList = async () => { + setSolutionList([]); + POSSIBLE_LEVEL.forEach((level) => { + requestSolutionListByLevelAPI(level).then((response) => { + const newSolutionList = response + .filter((solution) => solution.name !== "00-해답-예시.js") + .map((solution) => ({ + name: formattedFileName(solution.name), + level, + })); + + setSolutionList((solutionList) => [ + ...solutionList, + ...newSolutionList, + ]); + }); + }); + setSolutionList((solutionList) => + solutionList.sort((a, b) => a.level - b.level) + ); + }; + + return fetchSolutionList; +}; +export default useFetchSolutionList; +function formattedFileName(fileName) { + return fileName.replace(/-/g, " ").replace(".js", ""); +} diff --git a/src/hooks/solutionList/useSetSolutionList.js b/src/hooks/solutionList/useSetSolutionList.js new file mode 100644 index 0000000..8a0c233 --- /dev/null +++ b/src/hooks/solutionList/useSetSolutionList.js @@ -0,0 +1,7 @@ +import { useSetRecoilState } from "recoil"; +import solutionListState from "../../state/solutionList"; + +const useSetSolutionList = () => { + return useSetRecoilState(solutionListState); +}; +export default useSetSolutionList; diff --git a/src/hooks/solutionList/useSolutionListValue.js b/src/hooks/solutionList/useSolutionListValue.js new file mode 100644 index 0000000..f131f51 --- /dev/null +++ b/src/hooks/solutionList/useSolutionListValue.js @@ -0,0 +1,7 @@ +import { useRecoilValue } from "recoil"; +import solutionListState from "../../state/solutionList"; + +const useSolutionListValue = () => { + return useRecoilValue(solutionListState); +}; +export default useSolutionListValue; From f3141595ecbfd3927f7048406193cd09968693f7 Mon Sep 17 00:00:00 2001 From: codeisneverodd Date: Thu, 21 Jul 2022 10:29:46 +0900 Subject: [PATCH 7/9] =?UTF-8?q?feat:=20=EB=AC=B8=EC=A0=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EA=B2=80=EC=83=89=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/QuestionList.js | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) rename src/{pages/solutionReportPage => }/components/QuestionList.js (57%) diff --git a/src/pages/solutionReportPage/components/QuestionList.js b/src/components/QuestionList.js similarity index 57% rename from src/pages/solutionReportPage/components/QuestionList.js rename to src/components/QuestionList.js index 6b773dd..451f2d7 100644 --- a/src/pages/solutionReportPage/components/QuestionList.js +++ b/src/components/QuestionList.js @@ -1,18 +1,42 @@ import styled from "styled-components"; -import { TextInput } from "../../../style/styledComponents"; -import { useState } from "react"; +import { TextInput } from "../style/styledComponents"; +import { useEffect, useState } from "react"; +import useSolutionListValue from "../hooks/solutionList/useSolutionListValue"; +import { createFuzzyMatcher } from "./utils/createFuzzyMatcher"; -const QuestionList = () => { +const QuestionList = ({ onQuestionNameChange }) => { const [isQuestionListVisible, setIsQuestionListVisible] = useState(false); const [questionName, setQuestionName] = useState(""); + const solutionList = useSolutionListValue(); + const [questionList, setQuestionList] = useState([]); + + useEffect(() => { + setQuestionList(solutionList); + }, []); + + useEffect(() => { + onQuestionNameChange(questionName); + }, [questionName]); + function handleQuestionNameInput(e) { + const inputValue = e.target.value; + setQuestionName(inputValue); + const regex = createFuzzyMatcher(inputValue); + setQuestionList( + solutionList.filter((solution) => regex.test(solution.name)) + ); + if (!isQuestionListVisible) setIsQuestionListVisible(true); + } + function handleQuestionNameBlur(e) { + setIsQuestionListVisible(false); + } + function handleQuestionNameFocus(e) { + setIsQuestionListVisible(true); + } function handleQuestionClick(e) { + e.stopPropagation(); setIsQuestionListVisible(false); setQuestionName(e.target.dataset.value); } - function handleQuestionNameInput(e) { - setQuestionName(e.target.value); - if (!isQuestionListVisible) setIsQuestionListVisible(true); - } return ( <> @@ -21,17 +45,18 @@ const QuestionList = () => { placeholder="문제 이름을 검색하세요." defaultValue={questionName} value={questionName} + onFocus={handleQuestionNameFocus} onInput={handleQuestionNameInput} /> {isQuestionListVisible && ( - {[1, 2, 3, 4, 5].map((value) => ( - + {questionList.map((value, index) => ( + - {value}번 문제 + {value.name} / Level {value.level} ))} From e05eedcce72d0f8be62236147674be8e39bf8e7f Mon Sep 17 00:00:00 2001 From: codeisneverodd Date: Thu, 21 Jul 2022 10:30:35 +0900 Subject: [PATCH 8/9] =?UTF-8?q?feat:=20=EB=AC=B8=EC=A0=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=80=ED=84=B0=20=EA=B0=92=EC=9D=84=20=EB=B0=9B=EC=95=84?= =?UTF-8?q?=EC=98=AC=20=EC=88=98=20=EC=9E=88=EB=8A=94=20handleQuestionName?= =?UTF-8?q?Change=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/solutionReportPage/SolutionReport.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/pages/solutionReportPage/SolutionReport.js b/src/pages/solutionReportPage/SolutionReport.js index b9c0ebb..4b62f5a 100644 --- a/src/pages/solutionReportPage/SolutionReport.js +++ b/src/pages/solutionReportPage/SolutionReport.js @@ -15,7 +15,9 @@ import { useSearchParams } from "react-router-dom"; import { LOGIN_URL } from "./utils/gitHubLogin"; import useUserProfile from "../../hooks/user/useUserProfile"; import useUserLogin from "../../hooks/user/useUserLogin"; -import QuestionList from "./components/QuestionList"; +import QuestionList from "../../components/QuestionList"; +import useFetchSolutionList from "../../hooks/solutionList/useFetchSolutionList"; +import useSetSolutionList from "../../hooks/solutionList/useSetSolutionList"; export default function SolutionReport() { const [submitted, setSubmitted] = useState(false); @@ -23,6 +25,13 @@ export default function SolutionReport() { const [searchParams, setSearchParams] = useSearchParams(); const userInfo = useUserProfile(); const { isLoggedIn, requestLogin } = useUserLogin(); + const fetchSolutionList = useFetchSolutionList(); + const setSolutionList = useSetSolutionList(); + const [isFetched, setIsFetched] = useState(false); + useEffect(() => { + if (isFetched) fetchSolutionList(); + setIsFetched(true); + }, [isFetched, setIsFetched, fetchSolutionList]); useEffect(() => { if (searchParams.get("code")) { @@ -47,7 +56,9 @@ export default function SolutionReport() { function handleSubmitBtnClick() { setSubmitted(true); } - + function handleQuestionNameChange(e) { + console.log(e); + } return ( <>
@@ -63,7 +74,7 @@ export default function SolutionReport() { 문제 이름 - + {/*isDetailContentVisible &&*/} From 567d1c6ea9ad41aeea3d8385b6f75a6c4fc1cadb Mon Sep 17 00:00:00 2001 From: codeisneverodd Date: Thu, 21 Jul 2022 10:49:25 +0900 Subject: [PATCH 9/9] =?UTF-8?q?feat:=20ErrorReport=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=9D=98=20QuestionList=EB=A5=BC=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=EB=A1=9C=20=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...uestionList.js => QuestionInputAndList.js} | 24 ++++++++++--------- src/pages/errorReportPage/ErrorReport.js | 12 +++++++--- .../solutionReportPage/SolutionReport.js | 6 +++-- 3 files changed, 26 insertions(+), 16 deletions(-) rename src/components/{QuestionList.js => QuestionInputAndList.js} (86%) diff --git a/src/components/QuestionList.js b/src/components/QuestionInputAndList.js similarity index 86% rename from src/components/QuestionList.js rename to src/components/QuestionInputAndList.js index 451f2d7..917438a 100644 --- a/src/components/QuestionList.js +++ b/src/components/QuestionInputAndList.js @@ -4,25 +4,27 @@ import { useEffect, useState } from "react"; import useSolutionListValue from "../hooks/solutionList/useSolutionListValue"; import { createFuzzyMatcher } from "./utils/createFuzzyMatcher"; -const QuestionList = ({ onQuestionNameChange }) => { - const [isQuestionListVisible, setIsQuestionListVisible] = useState(false); +const QuestionInputAndList = ({ onQuestionNameChange = () => {} }) => { const [questionName, setQuestionName] = useState(""); - const solutionList = useSolutionListValue(); const [questionList, setQuestionList] = useState([]); + const [isQuestionListVisible, setIsQuestionListVisible] = useState(false); + const solutionList = useSolutionListValue(); useEffect(() => { setQuestionList(solutionList); }, []); - useEffect(() => { onQuestionNameChange(questionName); }, [questionName]); + function handleQuestionNameInput(e) { const inputValue = e.target.value; setQuestionName(inputValue); - const regex = createFuzzyMatcher(inputValue); + const findMatchedNameRegex = createFuzzyMatcher(inputValue); setQuestionList( - solutionList.filter((solution) => regex.test(solution.name)) + solutionList.filter((solution) => + findMatchedNameRegex.test(solution.name) + ) ); if (!isQuestionListVisible) setIsQuestionListVisible(true); } @@ -33,7 +35,6 @@ const QuestionList = ({ onQuestionNameChange }) => { setIsQuestionListVisible(true); } function handleQuestionClick(e) { - e.stopPropagation(); setIsQuestionListVisible(false); setQuestionName(e.target.dataset.value); } @@ -49,7 +50,7 @@ const QuestionList = ({ onQuestionNameChange }) => { onInput={handleQuestionNameInput} /> {isQuestionListVisible && ( - + {questionList.map((value, index) => ( { ))} - + )} ); }; -export default QuestionList; -export const Wrapper = styled.ul` +export default QuestionInputAndList; + +export const QuestionList = styled.ul` //display: none; position: absolute; top: 20rem; diff --git a/src/pages/errorReportPage/ErrorReport.js b/src/pages/errorReportPage/ErrorReport.js index 33ca37b..e668ba1 100644 --- a/src/pages/errorReportPage/ErrorReport.js +++ b/src/pages/errorReportPage/ErrorReport.js @@ -10,6 +10,7 @@ import { TextArea, ThanksMsg, } from "../../style/styledComponents"; +import QuestionInputAndList from "../../components/QuestionInputAndList"; export default function ErrorReport() { const [submitted, setSubmitted] = useState(false); @@ -47,7 +48,9 @@ export default function ErrorReport() { function handleSubmitBtnClick() { setSubmitted(true); } - + function handleQuestionNameChange(e) { + setQuestionName(e); + } return ( <>
@@ -106,13 +109,16 @@ export default function ErrorReport() { {isQuestionNameVisible && ( 문제 이름 + {/**/} - {/**/} + {/**/} {/* */} {/* 1번문제*/} {/* */} @@ -137,7 +143,7 @@ export default function ErrorReport() { {/* */} {/* 8번문제*/} {/* */} - {/**/} + {/**/} )} diff --git a/src/pages/solutionReportPage/SolutionReport.js b/src/pages/solutionReportPage/SolutionReport.js index 4b62f5a..a265644 100644 --- a/src/pages/solutionReportPage/SolutionReport.js +++ b/src/pages/solutionReportPage/SolutionReport.js @@ -15,7 +15,7 @@ import { useSearchParams } from "react-router-dom"; import { LOGIN_URL } from "./utils/gitHubLogin"; import useUserProfile from "../../hooks/user/useUserProfile"; import useUserLogin from "../../hooks/user/useUserLogin"; -import QuestionList from "../../components/QuestionList"; +import QuestionInputAndList from "../../components/QuestionInputAndList"; import useFetchSolutionList from "../../hooks/solutionList/useFetchSolutionList"; import useSetSolutionList from "../../hooks/solutionList/useSetSolutionList"; @@ -74,7 +74,9 @@ export default function SolutionReport() { 문제 이름 - + {/*isDetailContentVisible &&*/}