From 1181a3c2311d6341417ff7a05ded4b6a9ceca474 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Wed, 17 Jan 2024 19:39:15 +0900 Subject: [PATCH 01/17] =?UTF-8?q?refactor(mentor):=20useMemo=20=ED=9B=85?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=20=ED=95=A8=EC=88=98=EB=AA=85=20=EB=AA=85?= =?UTF-8?q?=EC=82=AC=20=EB=B3=80=EA=B2=BD,=20interface=EB=AA=85=20?= =?UTF-8?q?=EB=B0=8F=20=EC=84=A0=EC=96=B8=EB=AC=B8=20=EC=A4=91=EC=B2=A9?= =?UTF-8?q?=EC=97=86=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/common/Card.tsx | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/components/common/Card.tsx b/components/common/Card.tsx index 731b77ee5..9da53fb5c 100644 --- a/components/common/Card.tsx +++ b/components/common/Card.tsx @@ -8,18 +8,16 @@ import NoImg from '@/public/assets/icons/card/card_no-img.svg'; import kebab from '@/public/assets/icons/card/kebab.svg'; import styles from '@/styles/card/card.module.css'; -interface Link { - link: { - id: string; - createdAt: string; - url: string; - title: string; - description: string; - imageSource: string; - }; +interface LinkProps { + id: string; + createdAt: string; + url: string; + title: string; + description: string; + imageSource: string; } -export default function Card({ link }: Link) { +export default function Card({ link }: { link: LinkProps }) { const { id, createdAt, url, title, description, imageSource } = link; const [linkInfo, setLinkInfo] = useState({ id: '', @@ -43,7 +41,7 @@ export default function Card({ link }: Link) { }); }; - const getCreatedAt = useMemo(() => { + const yearMonthDay = useMemo(() => { const [year, month, day] = calCreatedDates(createdAt); setMins(calCreatedAt(year, month, day)); return { year, month, day }; @@ -92,7 +90,7 @@ export default function Card({ link }: Link) { imgSrc={kebab} title={title} description={description} - createdDates={getCreatedAt} + createdDates={yearMonthDay} linkInfo={linkInfo} /> From 6f6c27d66d21171077d3a6dc0f37fcb372fe41a5 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Wed, 17 Jan 2024 19:51:54 +0900 Subject: [PATCH 02/17] =?UTF-8?q?chore:=20jsx=EB=AC=B8=EC=97=90=EC=84=9C?= =?UTF-8?q?=20single=20quote=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20eslint=20/=20prettier=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.json | 9 +++++---- .prettierrc | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index b21aa6c7c..434a1f222 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,11 +7,11 @@ "createDefaultProgram": true }, "env": { - "browser": true, + "browser": true, "node": true, "es6": true }, - "ignorePatterns": ["node_modules/"], + "ignorePatterns": ["node_modules/"], "extends": [ "airbnb", "airbnb-typescript", @@ -19,11 +19,12 @@ "next/core-web-vitals", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended", - "prettier" + "prettier" ], "rules": { + "jsx-quotes": ["error", "prefer-single"], "react/react-in-jsx-scope": "off", "react/jsx-filename-extension": ["warn", { "extensions": [".ts", ".tsx"] }], - "no-useless-catch": "off" + "no-useless-catch": "off" } } diff --git a/.prettierrc b/.prettierrc index 863885b97..7b8dbf4d9 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,7 @@ { "semi": true, "singleQuote": true, + "jsxSingleQuote": true, "tabWidth": 2, "trailingComma": "all" } From 827d3532d802603a4dbc145ed44edfc0ceaaa74d Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Wed, 17 Jan 2024 21:40:28 +0900 Subject: [PATCH 03/17] =?UTF-8?q?refactor(mentor)=20:=20setKeyword?= =?UTF-8?q?=EC=97=90=20=EA=B0=9D=EC=B2=B4=EB=A1=9C=20state=20=EA=B0=92=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=ED=95=98=EB=8D=98=20=EA=B2=83=20=EC=88=98?= =?UTF-8?q?=EC=A0=95,=20single=20quote=EB=A1=9C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/common/SearchBar.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/components/common/SearchBar.tsx b/components/common/SearchBar.tsx index bb4e0bc76..7afa37fb8 100644 --- a/components/common/SearchBar.tsx +++ b/components/common/SearchBar.tsx @@ -14,10 +14,10 @@ export default function SearchBar() { const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Backspace' && router.query.keyword === '') { - setKeyword(router.query); + setKeyword(router.query.keyword); } if (e.key === 'Enter') { - setKeyword(router.query); + setKeyword(router.query.keyword); if (!router.query.keyword) return; setIsSearchResultShowed(true); } @@ -59,19 +59,19 @@ export default function SearchBar() { className={`${styles.searchbarInput} ${ isSearchActive ? styles.active : styles.inactive }`} - name="keyword" - type="text" - placeholder="링크를 검색해 보세요." + name='keyword' + type='text' + placeholder='링크를 검색해 보세요.' onChange={(e) => handleKeywordChange(e)} onKeyDown={(e) => handleKeyDown(e)} /> From 10c8d88020249963d12d934ce361df684b6e9201 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Wed, 17 Jan 2024 21:42:17 +0900 Subject: [PATCH 04/17] =?UTF-8?q?refactor(mentor):=20isEyeClicked=20->isPa?= =?UTF-8?q?sswordVisible=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20input=20value?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=80=EC=9E=A5=ED=95=A0=20state=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/common/auth/Input.tsx | 34 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/components/common/auth/Input.tsx b/components/common/auth/Input.tsx index cc077265b..3dec72aa6 100644 --- a/components/common/auth/Input.tsx +++ b/components/common/auth/Input.tsx @@ -4,27 +4,28 @@ import styles from '@/styles/auth/auth.module.css'; export default function Input({ type, - name, placeholder, - onClick, onBlurInput, errorMsg, }: { type: string; - name?: string; placeholder: string; - onClick?: any; onBlurInput: (value: string) => any; errorMsg: string; }) { - const [isEyeClicked, setIsEyeClicked] = useState(false); + const [isPasswordVisible, setIsPasswordVisible] = useState(false); + const [inputValue, setInputValue] = useState(''); const handleEyeClick = () => { - setIsEyeClicked((prev) => !prev); + setIsPasswordVisible((prev) => !prev); }; - const handleOnBlur = (e: React.FocusEvent) => { - onBlurInput(e.target.value); + const handleOnChange = (e: React.ChangeEvent) => { + setInputValue(e.target.value); + }; + + const handleOnBlur = () => { + onBlurInput(inputValue); }; return ( @@ -32,9 +33,10 @@ export default function Input({
handleOnBlur(e)} + onChange={(e) => handleOnChange(e)} + onBlur={handleOnBlur} name={type} - type={type === 'password' && isEyeClicked ? 'text' : type} + type={type === 'password' && isPasswordVisible ? 'text' : type} className={ errorMsg ? `${styles.textfieldInput} ${styles.errorInput}` @@ -43,23 +45,23 @@ export default function Input({ /> {type === 'password' && ( From 072b67d556a43ad6378d4bb68621a0d13a94dc98 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Wed, 17 Jan 2024 21:44:12 +0900 Subject: [PATCH 05/17] =?UTF-8?q?refactor(mentor):=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=ED=82=A4=EC=9B=8C=EB=93=9C=20=EB=B3=B4=EC=97=AC=EC=A3=BC?= =?UTF-8?q?=EB=8A=94=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EC=97=90?= =?UTF-8?q?=EC=84=9C=20keyword=20context=EC=97=90=EC=84=9C=20=EB=B6=88?= =?UTF-8?q?=EB=9F=AC=EC=98=A4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/common/SearchResult.tsx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/components/common/SearchResult.tsx b/components/common/SearchResult.tsx index ab0642979..c20e31df2 100644 --- a/components/common/SearchResult.tsx +++ b/components/common/SearchResult.tsx @@ -1,16 +1,14 @@ -import { useRouter } from 'next/router'; +import { useContext } from 'react'; +import FolderContext from '@/contexts/FolderContext'; import styles from '@/styles/search/searchResult.module.css'; export default function SearchResult() { - const router = useRouter(); - const search = router.query.keyword; + const { keyword } = useContext(FolderContext); return ( - <> - - {search} - 으로 검색한 결과입니다. - - + + {keyword} + 으로 검색한 결과입니다. + ); } From 1beb0492a9c225593d4ad390a4accc53f8f7666e Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Wed, 17 Jan 2024 21:47:29 +0900 Subject: [PATCH 06/17] =?UTF-8?q?refactor(mentor):=20authInfo=EC=99=80=20e?= =?UTF-8?q?rrorMsg=EB=A5=BC=20=ED=95=98=EB=82=98=EC=9D=98=20state=EB=A1=9C?= =?UTF-8?q?=20=ED=86=B5=ED=95=A9,=20signin/signup=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=8B=9C=20try=20catch=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/signin/index.tsx | 86 ++++++++++------------ pages/signup/index.tsx | 162 ++++++++++++++++++++--------------------- 2 files changed, 116 insertions(+), 132 deletions(-) diff --git a/pages/signin/index.tsx b/pages/signin/index.tsx index 1d8faefd3..4e7ff7c7b 100644 --- a/pages/signin/index.tsx +++ b/pages/signin/index.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; import { useRouter } from 'next/router'; -import { postSignin } from '@/utils/api'; +import { signin } from '@/utils/api'; import { getToken, setToken } from '@/utils/auth'; import { validateEmail } from '@/utils/validation'; import AuthButton from '@/components/common/auth/AuthButton'; @@ -11,71 +11,63 @@ import styles from '@/styles/auth/auth.module.css'; export default function Signin() { const router = useRouter(); - const [authInfo, setAuthInfo] = useState({ - email: '', - password: '', - }); - const [errorMsg, setErrorMsg] = useState({ - email: '', - password: '', + const [form, setForm] = useState({ + email: { + value: '', + errorMsg: '', + }, + password: { + value: '', + errorMsg: '', + }, }); const emailOnBlurInput = (value: string): void => { if (!value) { - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - email: '이메일을 입력해주세요', + email: { value: '', errorMsg: '이메일을 입력해주세요' }, })); - setAuthInfo((prev) => ({ ...prev, email: '' })); return; } if (!validateEmail(value)) { - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - email: '올바른 이메일 주소가 아닙니다.', + email: { value: '', errorMsg: '올바른 이메일 주소가 아닙니다.' }, })); - setAuthInfo((prev) => ({ ...prev, email: '' })); return; } - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - email: '', + email: { value: value, errorMsg: '' }, })); - setAuthInfo((prev) => ({ ...prev, email: value })); }; const passwordOnBlurInput = (value: string): void => { if (!value) { - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - password: '비밀번호를 입력해주세요', + password: { ...prev.password, errorMsg: '비밀번호를 입력해주세요.' }, })); return; } - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - password: '', + password: { value, errorMsg: '' }, })); - setAuthInfo((prev) => ({ ...prev, password: value })); + return; }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); - if (!authInfo.email || !authInfo.password) return; - try { - const res = await postSignin({ - email: authInfo.email, - password: authInfo.password, - }); - console.log(res); - if (res.accessToken) { - setToken(res.accessToken); - router.replace('/folder'); - } else { - return; - } - } catch (e: any) { - throw new Error(`signup handleSubmit: ${e}`); + if (!form.email.value || !form.password.value) return; + const res = await signin({ + email: form.email.value, + password: form.password.value, + }); + if (res.accessToken) { + setToken(res.accessToken); + router.replace('/folder'); } }; @@ -90,21 +82,21 @@ export default function Signin() {
handleSubmit(e)}> - - + +
); diff --git a/pages/signup/index.tsx b/pages/signup/index.tsx index 2c659f9d9..177392b06 100644 --- a/pages/signup/index.tsx +++ b/pages/signup/index.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import { useRouter } from 'next/router'; import { validateEmail, validatePassword } from '@/utils/validation'; -import { checkDuplicateEmail, postSignup } from '@/utils/api'; +import { checkDuplicateEmail, signup } from '@/utils/api'; import { getToken, setToken } from '@/utils/auth'; import TextField from '@/components/common/auth/TextField'; import AuthHeader from '@/components/common/auth/AuthHeader'; @@ -11,34 +11,34 @@ import styles from '@/styles/auth/auth.module.css'; export default function Signup() { const router = useRouter(); - const [authInfo, setAuthInfo] = useState({ - email: '', - password: '', - isPasswordConfirmed: false, - }); - const [errorMsg, setErrorMsg] = useState({ - email: '', - password: '', - passwordConfirmation: '', + const [form, setForm] = useState({ + email: { + value: '', + errorMsg: '', + }, + password: { + value: '', + errorMsg: '', + }, + passwordConfirmation: { + isConfirmed: false, + errorMsg: '', + }, }); const getEmailErrorMessage = async (value: string) => { - if (!authInfo.email) return; + if (!form.email.value) return; try { const res = await checkDuplicateEmail(value); if (res.error) { - setErrorMsg((prev) => ({ - ...prev, - email: res.error.message.toString(), - })); - setAuthInfo((prev) => ({ + setForm((prev) => ({ ...prev, - email: '', + email: { value: '', errorMsg: res.error.message.toString() }, })); } else { - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - email: '', + email: { ...prev.email, errorMsg: '' }, })); } } catch (e: any) { @@ -48,105 +48,97 @@ export default function Signup() { const emailOnBlurInput = (value: string): void => { if (!value) { - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - email: '이메일을 입력해주세요', + email: { value: '', errorMsg: '이메일을 입력하세요' }, })); - setAuthInfo((prev) => ({ ...prev, email: '' })); return; } if (!validateEmail(value)) { - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - email: '올바른 이메일이 아닙니다.', + email: { value: '', errorMsg: '올바른 이메일이 아닙니다.' }, })); - setAuthInfo((prev) => ({ ...prev, email: '' })); return; } - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - email: '', + email: { value: value, errorMsg: '' }, })); - setAuthInfo((prev) => ({ ...prev, email: value })); }; const passwordOnBlurInput = (value: string): void => { if (!value) { - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - password: '비밀번호를 입력해주세요', + password: { ...prev.password, errorMsg: '비밀번호를 입력하세요.' }, })); - return; } if (!validatePassword(value)) { - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - password: '비밀번호는 영문, 숫자 조합 8자 이상 입력해 주세요.', + password: { + ...prev.password, + errorMsg: '비밀번호는 영문, 숫자 조합 8자 이상 입력해 주세요.', + }, })); return; } - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - password: '', + password: { + value, + errorMsg: '', + }, })); - setAuthInfo((prev) => ({ ...prev, password: value })); }; const passwordConfirmOnBlurInput = (value: string): void => { if (!value) { - setErrorMsg((prev) => ({ + setForm((prev) => ({ ...prev, - passwordConfirmation: '비밀번호를 입력해주세요', - })); - setAuthInfo((prev) => ({ - ...prev, - isPasswordConfirmed: false, + passwordConfirmation: { + isConfirmed: false, + errorMsg: '비밀번호를 입력해주세요', + }, })); return; } - if (value !== authInfo.password) { - setErrorMsg((prev) => ({ - ...prev, - passwordConfirmation: '비밀번호가 일치하지 않아요.', - })); - setAuthInfo((prev) => ({ + if (value !== form.password.value) { + setForm((prev) => ({ ...prev, - isPasswordConfirmed: false, + passwordConfirmation: { + isConfirmed: false, + errorMsg: '비밀번호가 일치하지 않아요.', + }, })); return; } - setErrorMsg((prev) => ({ - ...prev, - passwordConfirmation: '', - })); - setAuthInfo((prev) => ({ + setForm((prev) => ({ ...prev, - isPasswordConfirmed: true, + passwordConfirmation: { + isConfirmed: true, + errorMsg: '', + }, })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); - if (!authInfo.isPasswordConfirmed || !authInfo.email) return; - try { - const res = await postSignup({ - email: authInfo.email, - password: authInfo.password, - }); - if (res.accessToken) { - setToken(res.accessToken); - router.replace('/folder'); - } else { - return; - } - } catch (e: any) { - throw new Error(`signup handleSubmit: ${e}`); + if (!form.passwordConfirmation.isConfirmed || !form.email.value) return; + const res = await signup({ + email: form.email.value, + password: form.password.value, + }); + if (res.accessToken) { + setToken(res.accessToken); + router.replace('/folder'); } }; useEffect(() => { - getEmailErrorMessage(authInfo.email); - }, [authInfo.email]); + getEmailErrorMessage(form.email.value); + }, [form.email]); useEffect(() => { const accessToken = getToken(); @@ -159,28 +151,28 @@ export default function Signup() {
handleSubmit(e)}> - - + + ); From 7364c521cd6d019362e5548b1e6d28184a378f0c Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Wed, 17 Jan 2024 21:48:26 +0900 Subject: [PATCH 07/17] =?UTF-8?q?refactor(mentor):=20signin/signup=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=EB=AA=85=20=EB=B3=80=EA=B2=BD,=20try=20catch?= =?UTF-8?q?=20=EB=AC=B8=EC=9D=98=20error=20=EB=B0=9C=EC=83=9D=EC=8B=9C=20a?= =?UTF-8?q?lert=20=EB=9D=84=EC=9A=B0=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/api.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/utils/api.ts b/utils/api.ts index 0434c21e1..fec280cb8 100644 --- a/utils/api.ts +++ b/utils/api.ts @@ -22,20 +22,28 @@ export async function checkDuplicateEmail(email: string) { } } -export async function postSignup(data: { email: string; password: string }) { +export async function signup(data: { email: string; password: string }) { try { const res = await axios.post('/sign-up', data); return res.data.data; } catch (e: any) { - if (e.response) return e.response.data; + if (!e.response) { + alert('회원가입에 실패했습니다.'); + } else { + return e.response.data; + } } } -export async function postSignin(data: { email: string; password: string }) { +export async function signin(data: { email: string; password: string }) { try { const res = await axios.post('/sign-in', data); return res.data.data; } catch (e: any) { - if (e.response) return e.response.data; + if (!e.response) { + alert('로그인에 실패했습니다.'); + } else { + return e.response.data; + } } } From 93f99deeeaab485fe4eb52d145b45ea27d640b93 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Wed, 17 Jan 2024 22:24:34 +0900 Subject: [PATCH 08/17] =?UTF-8?q?refactor(mentor):=20context=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EB=93=A4=20tsx=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contexts/FolderContext.jsx | 41 ---------------------- contexts/FolderContext.tsx | 70 ++++++++++++++++++++++++++++++++++++++ contexts/KebabContext.jsx | 28 --------------- contexts/KebabContext.tsx | 42 +++++++++++++++++++++++ 4 files changed, 112 insertions(+), 69 deletions(-) delete mode 100644 contexts/FolderContext.jsx create mode 100644 contexts/FolderContext.tsx delete mode 100644 contexts/KebabContext.jsx create mode 100644 contexts/KebabContext.tsx diff --git a/contexts/FolderContext.jsx b/contexts/FolderContext.jsx deleted file mode 100644 index f5506141b..000000000 --- a/contexts/FolderContext.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import { createContext, useState } from 'react'; - -const FolderContext = createContext(); - -export function FolderContextProvider({ children }) { - const [folderList, setFolderList] = useState([]); - const [clickedOption, setClickedOption] = useState({ - addFolderLink: false, - shareFolder: false, - editFolderName: false, - deleteFolder: false, - addNewFolder: false, - }); - const [addedLink, setAddedLink] = useState(''); - const [keyword, setKeyword] = useState(''); - const [filteredLinks, setFilteredLinks] = useState([]); - const [isSearchResultShowed, setIsSearchResultShowed] = useState(false); - - return ( - - {children} - - ); -} - -export default FolderContext; diff --git a/contexts/FolderContext.tsx b/contexts/FolderContext.tsx new file mode 100644 index 000000000..b3c58845a --- /dev/null +++ b/contexts/FolderContext.tsx @@ -0,0 +1,70 @@ +import { Dispatch, SetStateAction, createContext, useState } from 'react'; + +interface FolderContextProps { + clickedOption: { + addFolderLink: boolean; + shareFolder: boolean; + editFolderName: boolean; + deleteFolder: boolean; + addNewFolder: boolean; + }; + setClickedOption: Dispatch< + SetStateAction<{ + addFolderLink: boolean; + shareFolder: boolean; + editFolderName: boolean; + deleteFolder: boolean; + addNewFolder: boolean; + }> + >; + addedLink: string; + setAddedLink: Dispatch>; + folderList: {}[]; + setFolderList: Dispatch>; + keyword: string; + setKeyword: Dispatch>; + filteredLinks: {}[]; + setFilteredLinks: Dispatch>; + isSearchResultShowed: boolean; + setIsSearchResultShowed: Dispatch>; +} + +const FolderContext = createContext(undefined); + +export function FolderContextProvider({ children }: any) { + const [folderList, setFolderList] = useState<{}[]>([]); + const [clickedOption, setClickedOption] = useState({ + addFolderLink: false, + shareFolder: false, + editFolderName: false, + deleteFolder: false, + addNewFolder: false, + }); + const [addedLink, setAddedLink] = useState(''); + const [keyword, setKeyword] = useState(''); + const [filteredLinks, setFilteredLinks] = useState<{}[]>([]); + const [isSearchResultShowed, setIsSearchResultShowed] = useState(false); + + return ( + + {children} + + ); +} + +export default FolderContext; diff --git a/contexts/KebabContext.jsx b/contexts/KebabContext.jsx deleted file mode 100644 index 7b4c863fc..000000000 --- a/contexts/KebabContext.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import { createContext, useState } from 'react'; - -const KebabContext = createContext(); - -export function KebabContextProvider({ children }) { - const [clickedKebabOption, setClickedKebabOption] = useState({ - delete: false, - addToFolder: false, - }); - - const closeKebab = () => { - setClickedKebabOption({ delete: false, addToFolder: false }); - }; - - return ( - - {children} - - ); -} - -export default KebabContext; diff --git a/contexts/KebabContext.tsx b/contexts/KebabContext.tsx new file mode 100644 index 000000000..ef01b3e5d --- /dev/null +++ b/contexts/KebabContext.tsx @@ -0,0 +1,42 @@ +import { Dispatch, SetStateAction, createContext, useState } from 'react'; + +interface KebabContextProps { + clickedKebabOption: { + delete: boolean; + addToFolder: boolean; + }; + setClickedKebabOption: Dispatch< + SetStateAction<{ + delete: boolean; + addToFolder: boolean; + }> + >; + closeKebab: () => void; +} + +const KebabContext = createContext(undefined); + +export function KebabContextProvider({ children }: any) { + const [clickedKebabOption, setClickedKebabOption] = useState({ + delete: false, + addToFolder: false, + }); + + const closeKebab = () => { + setClickedKebabOption({ delete: false, addToFolder: false }); + }; + + return ( + + {children} + + ); +} + +export default KebabContext; From ef79929c8b2bc6ceb3c60fd7c729fc0645a41005 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Fri, 19 Jan 2024 23:56:02 +0900 Subject: [PATCH 09/17] =?UTF-8?q?chore:=20react-hook-form=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 32 ++++++++++++++++++++------------ package.json | 5 +++-- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 809fc2338..b83b3e120 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,11 @@ "name": "ts-nextjs-weekly", "version": "0.1.0", "dependencies": { + "axios": "^1.6.5", "next": "14.0.4", "react": "^18", "react-dom": "^18", + "react-hook-form": "^7.49.3", "styled-components": "^6.1.8" }, "devDependencies": { @@ -19,7 +21,6 @@ "@types/react-dom": "^18", "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", - "axios": "^1.6.5", "eslint": "^8.2.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.1.0", @@ -878,8 +879,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/available-typed-arrays": { "version": "1.0.5", @@ -906,7 +906,6 @@ "version": "1.6.5", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", - "dev": true, "dependencies": { "follow-redirects": "^1.15.4", "form-data": "^4.0.0", @@ -1051,7 +1050,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1183,7 +1181,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -2199,7 +2196,6 @@ "version": "1.15.4", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", - "dev": true, "funding": [ { "type": "individual", @@ -2228,7 +2224,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -3080,7 +3075,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -3089,7 +3083,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -3490,8 +3483,7 @@ "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/punycode": { "version": "2.3.1", @@ -3545,6 +3537,22 @@ "react": "^18.2.0" } }, + "node_modules/react-hook-form": { + "version": "7.49.3", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.49.3.tgz", + "integrity": "sha512-foD6r3juidAT1cOZzpmD/gOKt7fRsDhXXZ0y28+Al1CHgX+AY1qIN9VSIIItXRq1dN68QrRwl1ORFlwjBaAqeQ==", + "engines": { + "node": ">=18", + "pnpm": "8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index 0c37440fa..27602f6a5 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,12 @@ "lint": "next lint" }, "dependencies": { + "axios": "^1.6.5", "next": "14.0.4", "react": "^18", "react-dom": "^18", - "styled-components": "^6.1.8", - "axios": "^1.6.5" + "react-hook-form": "^7.49.3", + "styled-components": "^6.1.8" }, "devDependencies": { "@types/node": "^20", From b8eb305cb528dcea447a10e91589f6f0dd8b73f7 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Sat, 20 Jan 2024 00:25:59 +0900 Subject: [PATCH 10/17] =?UTF-8?q?chore:=20pages/shared.tsx=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=ED=9B=84=20pages/shared/index.tsx=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/{shared.tsx => shared/index.tsx} | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) rename pages/{shared.tsx => shared/index.tsx} (93%) diff --git a/pages/shared.tsx b/pages/shared/index.tsx similarity index 93% rename from pages/shared.tsx rename to pages/shared/index.tsx index 2f2a49acd..039e3d57b 100644 --- a/pages/shared.tsx +++ b/pages/shared/index.tsx @@ -9,8 +9,11 @@ import CardWrapper from '@/components/common/CardWrapper'; import styles from '@/styles/header/mainHeader.module.css'; export default function Shared() { - const { keyword, filteredLinks, setFilteredLinks } = - useContext(FolderContext); + const folderContext = useContext(FolderContext); + if (!folderContext) { + return null; + } + const { keyword, filteredLinks, setFilteredLinks } = folderContext; const [profileData, setProfileData] = useState({ id: 0, name: '', From fda532da1e55b53223637fb05d00f04a4fb62950 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Mon, 22 Jan 2024 00:23:08 +0900 Subject: [PATCH 11/17] =?UTF-8?q?refactor:=20localStorage=EB=A5=BC=20?= =?UTF-8?q?=EB=B6=88=EB=9F=AC=EC=98=AC=20=EC=88=98=20=EC=97=86=EC=9D=84=20?= =?UTF-8?q?=EB=95=8C=20null=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/auth.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/utils/auth.ts b/utils/auth.ts index e42722146..8252cdc8c 100644 --- a/utils/auth.ts +++ b/utils/auth.ts @@ -1,5 +1,9 @@ export const getToken = () => { - return localStorage.getItem('accessToken'); + const accessToken = + typeof localStorage !== 'undefined' + ? localStorage.getItem('accessToken') + : null; + return accessToken; }; export const setToken = (token: string) => { From 9cbf0e00d741a038b0cf10cbeca4b7e1aa7991e4 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Mon, 22 Jan 2024 00:23:46 +0900 Subject: [PATCH 12/17] =?UTF-8?q?feat:=20axios=20instance=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20headers=20=EC=84=A4=EC=A0=95,=20api=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EB=B3=84=EB=A1=9C=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/api.ts | 67 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/utils/api.ts b/utils/api.ts index fec280cb8..d6809a890 100644 --- a/utils/api.ts +++ b/utils/api.ts @@ -1,10 +1,67 @@ import axios from 'axios'; +import { getToken } from './auth'; -axios.defaults.baseURL = 'https://bootcamp-api.codeit.kr/api'; +const accessToken = getToken(); + +const instance = axios.create({ + baseURL: 'https://bootcamp-api.codeit.kr/api', + timeout: 5000, + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${accessToken}`, + }, +}); + +export async function getFolders() { + try { + const res = await instance.get('/folders'); + return res; + } catch (e) { + throw new Error(`getFolders ${e}`); + } +} + +export async function getUsers() { + try { + const res = await instance.get('/users'); + return res.data.data[0]; + } catch (e) { + throw new Error(`getUsers ${e}`); + } +} + +export async function getLinks(userId: number) { + try { + const res = await instance.get(`/users/${userId}/links`); + return res.data.data; + } catch (e) { + throw new Error(`getLinks ${e}`); + } +} + +export async function getAllFolders(userId: number) { + try { + const res = await instance.get(`/users/${userId}/folders`); + return res.data.data; + } catch (e) { + throw new Error(`getAllFolders ${e}`); + } +} + +export async function getLinksByFolder(userId: number, folderId: number) { + try { + const res = await instance.get( + `/users/${userId}/links?folderId=${folderId}`, + ); + return res.data.data; + } catch (e) { + throw new Error(`getLinksByFolder ${e}`); + } +} export async function getData(url: string) { try { - const response = await axios.get(`${url}`); + const response = await instance.get(`${url}`); return response.data; } catch (e) { throw new Error(`getData에서 ${e} 발생`); @@ -13,7 +70,7 @@ export async function getData(url: string) { export async function checkDuplicateEmail(email: string) { try { - const res = await axios.post('/check-email', { + const res = await instance.post('/check-email', { email: email, }); return res.data; @@ -24,7 +81,7 @@ export async function checkDuplicateEmail(email: string) { export async function signup(data: { email: string; password: string }) { try { - const res = await axios.post('/sign-up', data); + const res = await instance.post('/sign-up', data); return res.data.data; } catch (e: any) { if (!e.response) { @@ -37,7 +94,7 @@ export async function signup(data: { email: string; password: string }) { export async function signin(data: { email: string; password: string }) { try { - const res = await axios.post('/sign-in', data); + const res = await instance.post('/sign-in', data); return res.data.data; } catch (e: any) { if (!e.response) { From c31f92b8de0dfab687ef0ff73c0605a1786fcfae Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Mon, 22 Jan 2024 00:24:09 +0900 Subject: [PATCH 13/17] =?UTF-8?q?chore:=20img=20url=EC=97=90=20=EB=A7=9E?= =?UTF-8?q?=EA=B2=8C=20next.config=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- next.config.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/next.config.js b/next.config.js index 957e20aa7..2230eab2b 100644 --- a/next.config.js +++ b/next.config.js @@ -75,6 +75,18 @@ const nextConfig = { port: '', pathname: '/**', }, + { + protocol: 'https', + hostname: 'avatars.githubusercontent.com', + port: '', + pathname: '/**', + }, + { + protocol: 'https', + hostname: 'images.unsplash.com', + port: '', + pathname: '/**', + }, ], }, }; From fbba917298ef37218315001f169a28e2adc0eb10 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Mon, 22 Jan 2024 00:25:43 +0900 Subject: [PATCH 14/17] =?UTF-8?q?feat:=20folder=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=97=90=EC=84=9C=2014=EC=A3=BC=EC=B0=A8=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EA=B5=AC=ED=98=84([id]=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=9D=BC=EC=9A=B0=ED=84=B0=20?= =?UTF-8?q?=EC=A0=9C=EC=99=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/folder/index.tsx | 101 ++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 46 deletions(-) diff --git a/pages/folder/index.tsx b/pages/folder/index.tsx index 6b22aaac6..4e5bd865d 100644 --- a/pages/folder/index.tsx +++ b/pages/folder/index.tsx @@ -1,5 +1,11 @@ import { useContext, useEffect, useState } from 'react'; -import { getData } from '@/utils/api'; +import { + getAllFolders, + getFolders, + getLinks, + getLinksByFolder, + getUsers, +} from '@/utils/api'; import { filterByKeyword } from '@/utils/searchUtils'; import FolderContext from '@/contexts/FolderContext'; import Modal from '@/components/common/folderPage/modal/Modal'; @@ -12,8 +18,19 @@ import Nolinks from '@/components/common/folderPage/NoLinks'; import CardWrapper from '@/components/common/CardWrapper'; import FolderAddButton from '@/components/common/folderPage/FolderAddButton'; import styles from '@/styles/card/cardWrapper.module.css'; +import { getToken, setToken } from '@/utils/auth'; +import { useRouter } from 'next/router'; export default function Folder() { + const router = useRouter(); + const [profileData, setProfileData] = useState({ + id: 0, + created_at: '', + name: '', + image_source: '', + email: '', + auth_id: '', + }); const { addedLink, clickedOption, @@ -23,34 +40,24 @@ export default function Folder() { filteredLinks, setFilteredLinks, } = useContext(FolderContext); - const [profileData, setProfileData] = useState({ - id: 0, - created_at: '', - name: '', - image_source: '', - email: '', - auth_id: '', - }); const [links, setLinks] = useState([]); const [currentFolder, setCurrentFolder] = useState<{ - id: string; + id: number; name?: string; - }>({ id: '', name: '전체' }); + }>({ id: 0, name: '전체' }); const getUserData = async () => { try { - const result = await getData('users/1'); - const { id, created_at, name, image_source, email, auth_id } = - result.data[0]; - setProfileData((prevProfileData) => ({ - ...prevProfileData, + const result = await getUsers(); + const { id, created_at, name, image_source, email, auth_id } = result; + setProfileData({ id, created_at, name, image_source, email, auth_id, - })); + }); } catch (e) { throw new Error(`Folderpage getUserData ${e}`); } @@ -58,9 +65,9 @@ export default function Folder() { const getTotalLinksData = async () => { try { - const result = await getData('users/1/links'); - const { data } = result; - const links = data.map((link: any) => ({ + const result = await getLinks(profileData.id); + console.log(result, 'dd'); + const links = result.map((link: any) => ({ ...link, createdAt: link.created_at, imageSource: link.image_source, @@ -73,10 +80,9 @@ export default function Folder() { const getFolderList = async () => { try { - const result = await getData('users/1/folders'); - const { data } = result; - data.unshift({ name: '전체' }); - setFolderList(data); + const res = await getAllFolders(profileData.id); + res.unshift({ name: '전체' }); + setFolderList(res); } catch (e) { throw new Error(`Folderpage의 getFolderList에서 ${e} 발생`); } @@ -84,16 +90,13 @@ export default function Folder() { const getFolder = async () => { try { - const result = await getData( - `users/1/links?folderId=${currentFolder?.id}`, - ); - const { data } = result; - const datas = data.map((link: any) => ({ + const res = await getLinksByFolder(profileData.id, currentFolder.id); + const data = res.map((link: any) => ({ ...link, createdAt: link.created_at, imageSource: link.image_source, })); - setLinks(datas); + setLinks(data); } catch (e) { throw new Error( `Folderpage의 handleFolderClick의 getFolder에서 ${e} 발생`, @@ -101,26 +104,32 @@ export default function Folder() { } }; - const handleFolderClick = ( - e: React.MouseEvent, - ) => { - const textContent = e.currentTarget.textContent; - setCurrentFolder((prev) => ({ ...prev, name: textContent?.toString() })); - if (textContent === '전체') { + const handleFolderClick = (folderId: number) => { + if (!folderId) { + setCurrentFolder((prev) => ({ ...prev, name: '전체' })); getTotalLinksData(); return; } const clikedFolder: any = folderList.filter( - (folder: any) => folder.name === textContent, + (folder: any) => folder.id === folderId, ); setCurrentFolder(clikedFolder[0]); + if (folderId) { + router.push(`/folder/${folderId}`); + } }; useEffect(() => { + if (!getToken()) { + router.replace('/signin'); + } getUserData(); + }, []); + + useEffect(() => { getTotalLinksData(); getFolderList(); - }, []); + }, [profileData.id]); useEffect(() => { getFolder(); @@ -134,18 +143,18 @@ export default function Folder() { <> {clickedOption.addFolderLink && addedLink && ( )} {clickedOption.shareFolder && ( - + )} {clickedOption.editFolderName && ( )} {clickedOption.addNewFolder && ( @@ -179,7 +188,7 @@ export default function Folder() { return (
handleFolderClick(e)} + onClick={() => handleFolderClick(folder.id)} > + )}
@@ -213,7 +222,7 @@ export default function Folder() { )} )} - {!folderList.length && } + {!folderList.length && } ); From 5ebe5698ba6153cd0bef8767eb98a38d5dacd5b8 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Mon, 22 Jan 2024 00:26:23 +0900 Subject: [PATCH 15/17] =?UTF-8?q?refactor:=20context.tsx=EC=9D=98=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=98=A4=EB=A5=98=20=EB=95=8C=EB=AC=B8?= =?UTF-8?q?=EC=97=90=20=EC=9D=BC=EC=8B=9C=EC=A0=81=EC=9C=BC=EB=A1=9C=20jsx?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95=ED=95=98=EC=97=AC=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contexts/FolderContext.jsx | 35 ++++++++++++++++ ...olderContext.tsx => FolderContextTest.tsx} | 42 +++++++++++++++---- contexts/KebabContext.jsx | 28 +++++++++++++ ...{KebabContext.tsx => KebabContextTest.tsx} | 14 ++++--- 4 files changed, 105 insertions(+), 14 deletions(-) create mode 100644 contexts/FolderContext.jsx rename contexts/{FolderContext.tsx => FolderContextTest.tsx} (64%) create mode 100644 contexts/KebabContext.jsx rename contexts/{KebabContext.tsx => KebabContextTest.tsx} (66%) diff --git a/contexts/FolderContext.jsx b/contexts/FolderContext.jsx new file mode 100644 index 000000000..020af7b44 --- /dev/null +++ b/contexts/FolderContext.jsx @@ -0,0 +1,35 @@ +import { createContext, useState } from 'react'; + +const FolderContext = createContext(); + +export function FolderContextProvider({ children }) { + const [folderList, setFolderList] = useState([]); + const [clickedOption, setClickedOption] = useState({}); + const [addedLink, setAddedLink] = useState(''); + const [keyword, setKeyword] = useState(''); + const [filteredLinks, setFilteredLinks] = useState([]); + const [isSearchResultShowed, setIsSearchResultShowed] = useState(false); + + return ( + + {children} + + ); +} + +export default FolderContext; diff --git a/contexts/FolderContext.tsx b/contexts/FolderContextTest.tsx similarity index 64% rename from contexts/FolderContext.tsx rename to contexts/FolderContextTest.tsx index b3c58845a..315d1bc22 100644 --- a/contexts/FolderContext.tsx +++ b/contexts/FolderContextTest.tsx @@ -23,15 +23,33 @@ interface FolderContextProps { setFolderList: Dispatch>; keyword: string; setKeyword: Dispatch>; - filteredLinks: {}[]; - setFilteredLinks: Dispatch>; + filteredLinks: { + id: string; + createdAt: string; + url: string; + title: string; + description: string; + }[]; + setFilteredLinks: Dispatch< + SetStateAction< + { + id: string; + createdAt: string; + url: string; + title: string; + description: string; + }[] + > + >; isSearchResultShowed: boolean; setIsSearchResultShowed: Dispatch>; } -const FolderContext = createContext(undefined); +const FolderContextTest = createContext( + undefined, +); -export function FolderContextProvider({ children }: any) { +export function FolderContextTestProvider({ children }: any) { const [folderList, setFolderList] = useState<{}[]>([]); const [clickedOption, setClickedOption] = useState({ addFolderLink: false, @@ -42,11 +60,19 @@ export function FolderContextProvider({ children }: any) { }); const [addedLink, setAddedLink] = useState(''); const [keyword, setKeyword] = useState(''); - const [filteredLinks, setFilteredLinks] = useState<{}[]>([]); + const [filteredLinks, setFilteredLinks] = useState< + { + id: string; + createdAt: string; + url: string; + title: string; + description: string; + }[] + >([]); const [isSearchResultShowed, setIsSearchResultShowed] = useState(false); return ( - {children} - + ); } -export default FolderContext; +export default FolderContextTest; diff --git a/contexts/KebabContext.jsx b/contexts/KebabContext.jsx new file mode 100644 index 000000000..e92fb5408 --- /dev/null +++ b/contexts/KebabContext.jsx @@ -0,0 +1,28 @@ +import { Dispatch, SetStateAction, createContext, useState } from 'react'; + +const KebabContext = createContext(); + +export function KebabContextProvider({ children }) { + const [clickedKebabOption, setClickedKebabOption] = useState({ + delete: false, + addToFolder: false, + }); + + const closeKebab = () => { + setClickedKebabOption({ delete: false, addToFolder: false }); + }; + + return ( + + {children} + + ); +} + +export default KebabContext; diff --git a/contexts/KebabContext.tsx b/contexts/KebabContextTest.tsx similarity index 66% rename from contexts/KebabContext.tsx rename to contexts/KebabContextTest.tsx index ef01b3e5d..70fb6f888 100644 --- a/contexts/KebabContext.tsx +++ b/contexts/KebabContextTest.tsx @@ -1,6 +1,6 @@ import { Dispatch, SetStateAction, createContext, useState } from 'react'; -interface KebabContextProps { +interface KebabContextTestProps { clickedKebabOption: { delete: boolean; addToFolder: boolean; @@ -14,9 +14,11 @@ interface KebabContextProps { closeKebab: () => void; } -const KebabContext = createContext(undefined); +const KebabContextTest = createContext( + undefined, +); -export function KebabContextProvider({ children }: any) { +export function KebabContextTestProvider({ children }: any) { const [clickedKebabOption, setClickedKebabOption] = useState({ delete: false, addToFolder: false, @@ -27,7 +29,7 @@ export function KebabContextProvider({ children }: any) { }; return ( - {children} - + ); } -export default KebabContext; +export default KebabContextTest; From 7e1088f70451cb2a2f5d2b93aeca26bea2e55b72 Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Mon, 22 Jan 2024 00:27:24 +0900 Subject: [PATCH 16/17] =?UTF-8?q?chore:=20double=20quote=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20single=20quote=EB=A1=9C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=ED=8F=AC=EB=A7=B7=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/common/Card.tsx | 2 +- components/common/folderPage/Dropdown.tsx | 4 ++-- pages/index.tsx | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/components/common/Card.tsx b/components/common/Card.tsx index 9da53fb5c..5ae51adb3 100644 --- a/components/common/Card.tsx +++ b/components/common/Card.tsx @@ -55,7 +55,7 @@ export default function Card({ link }: { link: LinkProps }) {
- + {imageSource ? ( {clickedKebabOption.delete && ( Linkbrary - - + + - +
From 3840261ec1c2e61ea770f8fb803acc12340987ed Mon Sep 17 00:00:00 2001 From: grapefruit13 Date: Mon, 22 Jan 2024 00:29:47 +0900 Subject: [PATCH 17/17] =?UTF-8?q?refactor:=20props=EC=97=90=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=EC=84=A4=EC=A0=95,=20props=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EA=B0=92=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/common/Header.tsx | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/components/common/Header.tsx b/components/common/Header.tsx index 1bf53d483..f67f64b01 100644 --- a/components/common/Header.tsx +++ b/components/common/Header.tsx @@ -3,23 +3,17 @@ import LoginButton from '@/components/common/LoginButton'; import Logo from '@/components/common/Logo'; import styles from '@/styles/header/header.module.css'; -interface Props { - profileData: { - id: number; - created_at?: string; - name: string; - image_source: string; - email: string; - auth_id?: string; - }; +interface HeaderProps { + id: number; + created_at?: string; + name: string; + image_source: string; + email: string; + auth_id?: string; } -export default function Header({ profileData }: Props) { - const { - name = 'defaultName', - image_source = 'https://images.unsplash.com/photo-1701600713610-0f724c65168d?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D', - email = 'default@email.com', - } = profileData; +export default function Header({ profileData }: { profileData: HeaderProps }) { + const { id, created_at, name, image_source, email, auth_id } = profileData; return (