From 766a0f86608a5d7a33152ca42383d3ca287c83f4 Mon Sep 17 00:00:00 2001 From: beom Date: Sun, 12 May 2024 16:16:20 +0900 Subject: [PATCH 01/24] =?UTF-8?q?feat=20:=20=EB=A6=AC=EC=95=A1=ED=8A=B8=20?= =?UTF-8?q?=EC=BF=BC=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 | 51 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 10 ++++++---- pages/_app.tsx | 23 ++++++++++++++++++++- pages/api/api.tsx | 3 ++- 4 files changed, 81 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index baa2b66555..ad286bea2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,8 @@ "name": "fe-weekly-mission", "version": "0.1.0", "dependencies": { + "@tanstack/react-query": "^5.35.5", + "@tanstack/react-query-devtools": "^5.35.5", "next": "13.5.6", "react": "^18", "react-dom": "^18" @@ -329,6 +331,55 @@ "tslib": "^2.4.0" } }, + "node_modules/@tanstack/query-core": { + "version": "5.35.5", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.35.5.tgz", + "integrity": "sha512-OMWvlEqG01RfGj+XZb/piDzPp0eZkkHWSDHt2LvE/fd1zWburP/xwm0ghk6Iv8cuPlP+ACFkZviKXK0OVt6lhg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.32.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.32.1.tgz", + "integrity": "sha512-7Xq57Ctopiy/4atpb0uNY5VRuCqRS/1fi/WBCKKX6jHMa6cCgDuV/AQuiwRXcKARbq2OkVAOrW2v4xK9nTbcCA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.35.5", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.35.5.tgz", + "integrity": "sha512-sppX7L+PVn5GBV3In6zzj0zcKfnZRKhXbX1MfIfKo1OjIq2GMaopvAFOP0x1bRYTUk2ikrdYcQYOozX7PWkb8A==", + "dependencies": { + "@tanstack/query-core": "5.35.5" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.35.5", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.35.5.tgz", + "integrity": "sha512-4Xll14B9uhgEJ+uqZZ5tqZ7G1LDR7wGYgb+NOZHGn11TTABnlV8GWon7zDMqdaHeR5mjjuY1UFo9pbz39kuZKQ==", + "dependencies": { + "@tanstack/query-devtools": "5.32.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.35.5", + "react": "^18.0.0" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", diff --git a/package.json b/package.json index 1ce24924fd..4a2f94d1f7 100644 --- a/package.json +++ b/package.json @@ -9,16 +9,18 @@ "lint": "next lint" }, "dependencies": { + "@tanstack/react-query": "^5.35.5", + "@tanstack/react-query-devtools": "^5.35.5", + "next": "13.5.6", "react": "^18", - "react-dom": "^18", - "next": "13.5.6" + "react-dom": "^18" }, "devDependencies": { - "typescript": "^5", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", "eslint": "^8", - "eslint-config-next": "13.5.6" + "eslint-config-next": "13.5.6", + "typescript": "^5" } } diff --git a/pages/_app.tsx b/pages/_app.tsx index 8e301a9e83..994edfc896 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,6 +1,27 @@ import "@/styles/reset.css"; +import React from "react"; import type { AppProps } from "next/app"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; export default function App({ Component, pageProps }: AppProps) { - return ; + const [queryClient] = React.useState( + () => + new QueryClient({ + defaultOptions: { + queries: { + // 보통 SSR에서는 staleTime을 0 이상으로 해줌으로써 + // 클라이언트 사이드에서 바로 다시 데이터를 refetch 하는 것을 피한다. + staleTime: 60 * 1000, + }, + }, + }) + ); + + return ( + + + + + ); } diff --git a/pages/api/api.tsx b/pages/api/api.tsx index 7679f92372..220c85b3a2 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -1,4 +1,5 @@ const BASE_URL = "https://bootcamp-api.codeit.kr"; +const BASE_URL2 = "https://bootcamp-api.codeit.kr/api/linkbrary/v1"; export async function getUser() { const response = await fetch(`${BASE_URL}/api/sample/user`); @@ -46,7 +47,7 @@ export async function getFolderLink(id: number) { } export async function postSignIn(id: string, password: string) { - const response = await fetch(`${BASE_URL}/api/sign-in`, { + const response = await fetch(`${BASE_URL2}/auth/sign-in`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ From 7a48590e05f6a2d522e9b18a892afabba92070ab Mon Sep 17 00:00:00 2001 From: beom Date: Sun, 12 May 2024 16:35:07 +0900 Subject: [PATCH 02/24] =?UTF-8?q?feat=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83=20api=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20(BaseUrl=20=EC=9D=B4=EB=A6=84=20=EC=B6=94=ED=9B=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=98=88=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/api/api.tsx | 2 +- pages/signin.tsx | 4 ++-- pages/signup.tsx | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pages/api/api.tsx b/pages/api/api.tsx index 220c85b3a2..0c00c70925 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -72,7 +72,7 @@ export async function postCheckEmail(id: string) { } export async function postSignUp(id: string, password: string) { - const response = await fetch(`${BASE_URL}/api/sign-up`, { + const response = await fetch(`${BASE_URL2}/auth/sign-up`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ diff --git a/pages/signin.tsx b/pages/signin.tsx index e7bcb134a8..6eb9983463 100644 --- a/pages/signin.tsx +++ b/pages/signin.tsx @@ -29,11 +29,11 @@ export default function SignIn() { const response = await postSignIn(emailValue, passwordValue); - const { data } = await response.json(); + const { accessToken } = await response.json(); if (response.status === 200) { router.push("/folder"); - localStorage.setItem("accessToken", data.accessToken); + localStorage.setItem("accessToken", accessToken); } else { setEmailError("이메일을 확인해 주세요."); setPasswordError("비밀번호를 확인해 주세요."); diff --git a/pages/signup.tsx b/pages/signup.tsx index 923c687930..9189edc6a6 100644 --- a/pages/signup.tsx +++ b/pages/signup.tsx @@ -33,10 +33,10 @@ export default function SignUp() { } else { //회원가입 로직 const response = await postSignUp(emailValue, passwordValue); - const { data } = await response.json(); + const { accessToken } = await response.json(); if (response.status === 200) { router.push("/folder"); - localStorage.setItem("accessToken", data.accessToken); + localStorage.setItem("accessToken", accessToken); } else { } } From e9664e984ea073ae3d066f98f72af27c2e45fe58 Mon Sep 17 00:00:00 2001 From: beom Date: Sun, 12 May 2024 16:49:50 +0900 Subject: [PATCH 03/24] =?UTF-8?q?feat=20:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20api=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20sha?= =?UTF-8?q?red,=20folder=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=A0=91?= =?UTF-8?q?=EA=B7=BC=20=EA=B6=8C=ED=95=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/api/api.tsx | 2 +- pages/folder.tsx | 6 ++++++ pages/shared.tsx | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pages/api/api.tsx b/pages/api/api.tsx index 0c00c70925..cb271901b5 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -60,7 +60,7 @@ export async function postSignIn(id: string, password: string) { } export async function postCheckEmail(id: string) { - const response = await fetch(`${BASE_URL}/api/check-email`, { + const response = await fetch(`${BASE_URL2}/users/check-email`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ diff --git a/pages/folder.tsx b/pages/folder.tsx index 202ea8b486..b1a04f5109 100644 --- a/pages/folder.tsx +++ b/pages/folder.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { useRouter } from "next/router"; import NavigationBar from "@/components/NavigationBar"; import Footer from "@/components/Footer"; import LinkAdd from "@/components/LinkAdd"; @@ -6,6 +7,11 @@ import FolderSection from "@/components/FolderSection"; import styles from "@/styles/FolderPage.module.css"; function FolderPage() { + const router = useRouter(); + + if (!localStorage.getItem("accessToken")) { + router.push("/signin"); + } return (
diff --git a/pages/shared.tsx b/pages/shared.tsx index 083772069f..3aa4a8c197 100644 --- a/pages/shared.tsx +++ b/pages/shared.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { useRouter } from "next/router"; import NavigationBar from "@/components/NavigationBar"; import FolderBar from "@/components/FolderBar"; import CardSection from "@/components/CardSection"; @@ -6,6 +7,12 @@ import Footer from "@/components/Footer"; import styles from "@/styles/SharedPage.module.css"; function SharedPage() { + const router = useRouter(); + + if (!localStorage.getItem("accessToken")) { + router.push("/signin"); + } + return (
From 02cd63aa320e46b93b957c7aa38f4d1144fcf173 Mon Sep 17 00:00:00 2001 From: beom Date: Sun, 12 May 2024 17:23:51 +0900 Subject: [PATCH 04/24] =?UTF-8?q?feat=20:=20=EB=84=A4=EB=B9=84=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=EB=B0=94=20api=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/NavigationBar.tsx | 31 ++++++------------------------- pages/api/api.tsx | 22 ++++++++++++++++++---- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/components/NavigationBar.tsx b/components/NavigationBar.tsx index 96317f3710..b2b84392ec 100644 --- a/components/NavigationBar.tsx +++ b/components/NavigationBar.tsx @@ -1,33 +1,14 @@ import React from "react"; import Image from "next/image"; import Link from "next/link"; -import { useEffect, useState } from "react"; +import { useQuery } from "@tanstack/react-query"; import { getUser } from "@/pages/api/api"; import styles from "@/styles/NavigationBar.module.css"; import Linkbrary from "@/public/images/logo.svg"; -interface ProfileObj { - profileImageSource: string; - email: string; -} - export default function NavigationBar() { - const [profile, setProfile] = useState(null); - - useEffect(() => { - async function getProFile() { - try { - const user = await getUser(); - if (user) { - setProfile(user); - } - } catch (error) { - console.error(error); - } - } - - getProFile(); - }, []); + const userInfo = useQuery({ queryKey: ["getUserInfo"], queryFn: getUser }); + const user = userInfo.data; return (
@@ -35,14 +16,14 @@ export default function NavigationBar() { Linkbrary - {profile ? ( + {user ? (
MyProfile - {profile.email} + {user[0].email}
) : ( diff --git a/pages/api/api.tsx b/pages/api/api.tsx index cb271901b5..b98156d9c6 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -2,12 +2,26 @@ const BASE_URL = "https://bootcamp-api.codeit.kr"; const BASE_URL2 = "https://bootcamp-api.codeit.kr/api/linkbrary/v1"; export async function getUser() { - const response = await fetch(`${BASE_URL}/api/sample/user`); - if (!response.ok) { + const token = localStorage.getItem("accessToken"); + + try { + const response = await fetch(`${BASE_URL2}/users`, { + method: "GET", + headers: { + Accept: "*/*", + Authorization: `Bearer ${token}`, + }, + }); + + if (!response.ok) { + throw new Error("유저 정보를 불러올 수 없습니다."); + } + + const user = await response.json(); + return user; + } catch (error) { throw new Error("유저 정보를 불러올 수 없습니다."); } - const user = await response.json(); - return user; } export async function getFolder() { From d417acc9a2e9ac0080eae33676d8e7d337e33df8 Mon Sep 17 00:00:00 2001 From: beom Date: Sun, 12 May 2024 18:59:36 +0900 Subject: [PATCH 05/24] =?UTF-8?q?feat=20:=20=ED=8F=B4=EB=8D=94=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=ED=8F=B4=EB=8D=94=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/FolderSection.tsx | 20 ++++++-------------- pages/api/api.tsx | 21 +++++++++++++++++---- pages/folder.tsx | 7 +------ 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/components/FolderSection.tsx b/components/FolderSection.tsx index c2ed1bc9aa..7d7c97c9ed 100644 --- a/components/FolderSection.tsx +++ b/components/FolderSection.tsx @@ -2,6 +2,7 @@ import React from "react"; import Image from "next/image"; import { useEffect, useState } from "react"; import { getFolderList, getAllLinks, getFolderLink } from "@/pages/api/api"; +import { useQuery } from "@tanstack/react-query"; import CardList from "@/components/CardList"; import SearchBar from "@/components/SearchBar"; import addImg from "@/public/images/add.svg"; @@ -29,7 +30,6 @@ interface CardListType { export default function FolderSection() { const [folderName, setFolderName] = useState("폴더를 선택해주세요"); - const [folderList, setFolderList] = useState([]); const [cardList, setCardList] = useState([]); const [isEditNameModal, setIsEditNameModal] = useState(false); const [isAddFolderModal, setIsAddFolderModal] = useState(false); @@ -79,18 +79,10 @@ export default function FolderSection() { //개별 폴더 클릭 //폴더 버튼 - useEffect(() => { - async function getList() { - try { - const { data } = await getFolderList(); - setFolderList(data); - } catch (error) { - console.error(error); - } - } - - getList(); - }, []); + const folderList = useQuery({ + queryKey: ["folderList"], + queryFn: async () => await getFolderList(), + }); //이름변경 아이콘 클릭시 뜨는 모달창 함수 const clickEditName = () => { @@ -155,7 +147,7 @@ export default function FolderSection() { > 전체 - {folderList.map(({ name, id }) => { + {folderList.data?.map(({ name, id }: FolderListType) => { return (
diff --git a/components/FolderBar.tsx b/components/FolderBar.tsx index 4364d469d9..bdc2ed0894 100644 --- a/components/FolderBar.tsx +++ b/components/FolderBar.tsx @@ -1,35 +1,35 @@ import React from "react"; -import { useEffect, useState } from "react"; -import { getFolder } from "@/pages/api/api"; +import { useQuery } from "@tanstack/react-query"; +import { getFolder, getFolderUser } from "@/pages/api/api"; import styles from "@/styles/FolderBar.module.css"; -export default function FolderBar() { - const [folderName, setFolderName] = useState(""); - const [userName, setUserName] = useState(""); - const [profileImage, setProfileImage] = useState(""); +export default function FolderBar({ id }: any) { + //폴더 이름을 가져오기 위한 쿼리 + const folderInfo = useQuery({ + queryKey: ["folderInfo"], + queryFn: async () => await getFolder(id), + }); - useEffect(() => { - async function getProFileFolder() { - try { - const { - folder: { name, owner }, - } = await getFolder(); - setFolderName(name); - setUserName(owner.name); - setProfileImage(owner.profileImageSource); - } catch (error) { - console.error(error); - } - } + //폴더 소유자를 가져오기 위한 쿼리 + const folderOwner = useQuery({ + queryKey: ["folderOwner"], + queryFn: async () => await getFolderUser(folderInfo.data[0].user_id), + }); - getProFileFolder(); - }, []); return (
- 폴더 이미지 - @{userName} - {folderName} + 폴더 이미지 + + @{folderOwner.data && folderOwner.data[0]?.name} + + + {folderInfo.data && folderInfo.data[0]?.name} +
); diff --git a/components/FolderSection.tsx b/components/FolderSection.tsx index 07c89fc7a8..e7a55e0c02 100644 --- a/components/FolderSection.tsx +++ b/components/FolderSection.tsx @@ -83,7 +83,6 @@ export default function FolderSection() { setCardList(allList.data); setFilteredCardList(allList.data); } - console.log(1111); }, [individualList.data, folderName, allList.data]); //폴더 버튼 @@ -182,7 +181,7 @@ export default function FolderSection() { />
- {cardList[0] ? ( + {cardList ?? cardList[0] ? ( <>
{folderName} diff --git a/pages/api/api.tsx b/pages/api/api.tsx index e041eb3081..9de9da68f4 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -1,6 +1,7 @@ const BASE_URL = "https://bootcamp-api.codeit.kr"; const BASE_URL2 = "https://bootcamp-api.codeit.kr/api/linkbrary/v1"; +//로그인에 필요한 api 함수 export async function getUser() { const token = localStorage.getItem("accessToken"); @@ -24,8 +25,19 @@ export async function getUser() { } } -export async function getFolder() { - const response = await fetch(`${BASE_URL}/api/sample/folder`); +//폴더 소유자의 정보를 얻기위한 api함수 +export async function getFolderUser(userId: number) { + const response = await fetch(`${BASE_URL2}/users/${userId}`); + if (!response.ok) { + throw new Error("폴더 정보를 불러올 수 없습니다."); + } + const folderUser = await response.json(); + return folderUser; +} + +//폴더의 정보를 얻기위한 api함수 +export async function getFolder(id: any) { + const response = await fetch(`${BASE_URL2}/folders/${id}`); if (!response.ok) { throw new Error("폴더 정보를 불러올 수 없습니다."); } @@ -33,6 +45,7 @@ export async function getFolder() { return folder; } +//현재 폴더 목록들을 얻기위한 api함수 export async function getFolderList() { const token = localStorage.getItem("accessToken"); try { @@ -55,6 +68,7 @@ export async function getFolderList() { } } +//전체 폴더의 링크 데이터를 얻기위한 api함수 export async function getAllLinks() { const token = localStorage.getItem("accessToken"); @@ -78,6 +92,7 @@ export async function getAllLinks() { } } +//개별 폴더의 링크 데이터를 얻기위한 api함수 export async function getFolderLink(id: number) { const response = await fetch(`${BASE_URL2}/folders/${id}/links`); if (!response.ok) { diff --git a/pages/shared.tsx b/pages/shared/[id].tsx similarity index 80% rename from pages/shared.tsx rename to pages/shared/[id].tsx index 3aa4a8c197..7f5387b03b 100644 --- a/pages/shared.tsx +++ b/pages/shared/[id].tsx @@ -8,16 +8,13 @@ import styles from "@/styles/SharedPage.module.css"; function SharedPage() { const router = useRouter(); - - if (!localStorage.getItem("accessToken")) { - router.push("/signin"); - } - + const { id } = router.query; + console.log(id); return (
- - + +
); From aa31f0168c4a96074210d400f74191d7f73addf7 Mon Sep 17 00:00:00 2001 From: beom Date: Sun, 12 May 2024 23:05:54 +0900 Subject: [PATCH 09/24] =?UTF-8?q?refactor=20:=20'=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=EB=90=9C=20=EB=A7=81=ED=81=AC=EA=B0=80=20=EC=97=86=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.'=20=EB=9C=A8=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/FolderSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/FolderSection.tsx b/components/FolderSection.tsx index e7a55e0c02..5795ec490d 100644 --- a/components/FolderSection.tsx +++ b/components/FolderSection.tsx @@ -181,7 +181,7 @@ export default function FolderSection() { />
- {cardList ?? cardList[0] ? ( + {cardList && cardList[0] ? ( <>
{folderName} From afc170ed5c71f40382864dab151feea0c0abb251 Mon Sep 17 00:00:00 2001 From: beom Date: Sun, 12 May 2024 23:07:31 +0900 Subject: [PATCH 10/24] =?UTF-8?q?refactor=20:=20=EC=A3=BC=EC=84=9D=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 --- components/CardSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/CardSection.tsx b/components/CardSection.tsx index 9b1ab01868..507c752d43 100644 --- a/components/CardSection.tsx +++ b/components/CardSection.tsx @@ -14,7 +14,7 @@ interface CardListType { } export default function CardSection({ id }: any) { - //카드 리스트들을 가져오기 위한 + //folderId 별로 카드 리스트들을 가져오기 위한 const cardList = useQuery({ queryKey: ["cardList"], queryFn: async () => await getFolderLink(id), From f03bf116fdee96e211acb9ab8cc8215dc9d5c728 Mon Sep 17 00:00:00 2001 From: beom Date: Mon, 13 May 2024 10:18:13 +0900 Subject: [PATCH 11/24] =?UTF-8?q?refactor=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20=EC=A3=BC=EC=84=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/api/api.tsx | 26 ++++++++++++++------------ pages/index.tsx | 4 ++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/pages/api/api.tsx b/pages/api/api.tsx index 9de9da68f4..e5f45fe65c 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -1,12 +1,11 @@ -const BASE_URL = "https://bootcamp-api.codeit.kr"; -const BASE_URL2 = "https://bootcamp-api.codeit.kr/api/linkbrary/v1"; +const BASE_URL = "https://bootcamp-api.codeit.kr/api/linkbrary/v1"; -//로그인에 필요한 api 함수 +//네비게이션바에 필요한 회원정보를 받아오는 api함수 export async function getUser() { const token = localStorage.getItem("accessToken"); try { - const response = await fetch(`${BASE_URL2}/users`, { + const response = await fetch(`${BASE_URL}/users`, { method: "GET", headers: { Accept: "*/*", @@ -27,7 +26,7 @@ export async function getUser() { //폴더 소유자의 정보를 얻기위한 api함수 export async function getFolderUser(userId: number) { - const response = await fetch(`${BASE_URL2}/users/${userId}`); + const response = await fetch(`${BASE_URL}/users/${userId}`); if (!response.ok) { throw new Error("폴더 정보를 불러올 수 없습니다."); } @@ -37,7 +36,7 @@ export async function getFolderUser(userId: number) { //폴더의 정보를 얻기위한 api함수 export async function getFolder(id: any) { - const response = await fetch(`${BASE_URL2}/folders/${id}`); + const response = await fetch(`${BASE_URL}/folders/${id}`); if (!response.ok) { throw new Error("폴더 정보를 불러올 수 없습니다."); } @@ -49,7 +48,7 @@ export async function getFolder(id: any) { export async function getFolderList() { const token = localStorage.getItem("accessToken"); try { - const response = await fetch(`${BASE_URL2}/folders`, { + const response = await fetch(`${BASE_URL}/folders`, { method: "GET", headers: { Accept: "*/*", @@ -73,7 +72,7 @@ export async function getAllLinks() { const token = localStorage.getItem("accessToken"); try { - const response = await fetch(`${BASE_URL2}/links`, { + const response = await fetch(`${BASE_URL}/links`, { method: "GET", headers: { Accept: "*/*", @@ -94,7 +93,7 @@ export async function getAllLinks() { //개별 폴더의 링크 데이터를 얻기위한 api함수 export async function getFolderLink(id: number) { - const response = await fetch(`${BASE_URL2}/folders/${id}/links`); + const response = await fetch(`${BASE_URL}/folders/${id}/links`); if (!response.ok) { throw new Error("해당 폴더 링크를 불러오는데 실패했습니다"); } @@ -102,8 +101,9 @@ export async function getFolderLink(id: number) { return folderLink; } +//로그인 요청을 위한 api함수 export async function postSignIn(id: string, password: string) { - const response = await fetch(`${BASE_URL2}/auth/sign-in`, { + const response = await fetch(`${BASE_URL}/auth/sign-in`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -115,8 +115,9 @@ export async function postSignIn(id: string, password: string) { return response; } +//이메일 중복 체크 api 함수 export async function postCheckEmail(id: string) { - const response = await fetch(`${BASE_URL2}/users/check-email`, { + const response = await fetch(`${BASE_URL}/users/check-email`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -127,8 +128,9 @@ export async function postCheckEmail(id: string) { return response; } +//회원가입 요청을 위한 api 함수 export async function postSignUp(id: string, password: string) { - const response = await fetch(`${BASE_URL2}/auth/sign-up`, { + const response = await fetch(`${BASE_URL}/auth/sign-up`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ diff --git a/pages/index.tsx b/pages/index.tsx index 598a78ae05..1598ae06f9 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -6,8 +6,8 @@ const inter = Inter({ subsets: ["latin"] }); export default function Home() { return ( <> - -

shared페이지로 이동

+ +

shared/1108페이지로 이동

folder페이지로 이동

From 812e73c954f8efb8e187a8901d8c3b6ed07bdf7b Mon Sep 17 00:00:00 2001 From: beom Date: Mon, 13 May 2024 12:15:44 +0900 Subject: [PATCH 12/24] =?UTF-8?q?feat=20:=20=EA=B3=B5=EC=9C=A0=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=AC=EC=B0=BD=EC=97=90=EC=84=9C=20shared=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20(=EC=BF=BC=EB=A6=AC?= =?UTF-8?q?=20=ED=82=A4=EB=A1=9C=20=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B8=B0=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=9E=84=EC=8B=9C=20=EA=B8=B0=EB=8A=A5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/CardSection.tsx | 7 ++----- components/FolderBar.tsx | 8 ++++++-- components/FolderSection.tsx | 15 ++++++++++++--- components/modal/Share.tsx | 25 ++++++++++++++++++++++--- pages/shared/[id].tsx | 3 +-- 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/components/CardSection.tsx b/components/CardSection.tsx index 507c752d43..b906f65b14 100644 --- a/components/CardSection.tsx +++ b/components/CardSection.tsx @@ -1,5 +1,4 @@ import React from "react"; -import { getFolderLink } from "@/pages/api/api"; import { useQuery } from "@tanstack/react-query"; import CardList from "@/components/CardList"; import SearchBar from "@/components/SearchBar"; @@ -14,10 +13,8 @@ interface CardListType { } export default function CardSection({ id }: any) { - //folderId 별로 카드 리스트들을 가져오기 위한 const cardList = useQuery({ - queryKey: ["cardList"], - queryFn: async () => await getFolderLink(id), + queryKey: ["individualList", Number(id)], }); const dummyFunc = () => {}; @@ -27,7 +24,7 @@ export default function CardSection({ id }: any) {
- {cardList.data && + {Array.isArray(cardList.data) && cardList.data.map( ({ id, diff --git a/components/FolderBar.tsx b/components/FolderBar.tsx index bdc2ed0894..68c3e0e118 100644 --- a/components/FolderBar.tsx +++ b/components/FolderBar.tsx @@ -7,13 +7,17 @@ export default function FolderBar({ id }: any) { //폴더 이름을 가져오기 위한 쿼리 const folderInfo = useQuery({ queryKey: ["folderInfo"], - queryFn: async () => await getFolder(id), + queryFn: () => getFolder(id), + enabled: id !== undefined, }); + console.log(id); + //폴더 소유자를 가져오기 위한 쿼리 const folderOwner = useQuery({ queryKey: ["folderOwner"], - queryFn: async () => await getFolderUser(folderInfo.data[0].user_id), + queryFn: () => getFolderUser(folderInfo.data[0].user_id), + enabled: !!folderInfo.data, }); return ( diff --git a/components/FolderSection.tsx b/components/FolderSection.tsx index 5795ec490d..a15fb46c1a 100644 --- a/components/FolderSection.tsx +++ b/components/FolderSection.tsx @@ -30,6 +30,7 @@ interface CardListType { export default function FolderSection() { const [folderName, setFolderName] = useState("폴더를 선택해주세요"); + const [folderId, setFolderId] = useState(null); //카드리스트에 관한 const [cardList, setCardList] = useState([]); const [filteredCardList, setFilteredCardList] = useState([]); @@ -54,6 +55,7 @@ export default function FolderSection() { //전체 폴더 클릭 async function folderAllNameClick() { setFolderName("전체"); + setFolderId(null); } //개별 폴더 가져오기 @@ -70,8 +72,9 @@ export default function FolderSection() { }); //개별 폴더 클릭 - async function folderNameClick(name: string) { + async function folderNameClick(name: string, id: number) { setFolderName(name); + setFolderId(id); } //폴더이름을 클릭했을 때 즉각적으로 링크 데이터들이 바뀌도록 @@ -139,7 +142,13 @@ export default function FolderSection() { )} {isAddFolderModal && } - {isShareModal && } + {isShareModal && ( + + )} {isDeleteFolderModal && ( )} @@ -161,7 +170,7 @@ export default function FolderSection() { key={id} className={selectedFolderId === id ? styles.active : ""} onClick={() => { - folderNameClick(name); + folderNameClick(name, id); setSelectedFolderId(id); setSelectedId(id); }} diff --git a/components/modal/Share.tsx b/components/modal/Share.tsx index 94f2945490..85660fbcbf 100644 --- a/components/modal/Share.tsx +++ b/components/modal/Share.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { useRouter } from "next/navigation"; import Image from "next/image"; import styles from "@/styles/Share.module.css"; import closeIcon from "@/public/images/close.svg"; @@ -7,11 +8,18 @@ import facebookIcon from "@/public/images/facebook_icon.svg"; import linkIcon from "@/public/images/link.svg"; interface ShareProps { + folderId: number | null; folderName: string; onClose: any; } -export default function Share({ folderName, onClose }: ShareProps) { +export default function Share({ folderId, folderName, onClose }: ShareProps) { + const router = useRouter(); + + const moveToSharePage = (id: number | null) => { + router.push(`/shared/${id}`); + }; + return (
@@ -27,19 +35,30 @@ export default function Share({ folderName, onClose }: ShareProps) { />
- kakaoIcon + moveToSharePage(folderId)} + alt="kakaoIcon" + />

카카오톡

moveToSharePage(folderId)} alt="facebookIcon" />

페이스북

- linkIcon + moveToSharePage(folderId)} + alt="linkIcon" + />

링크 복사

diff --git a/pages/shared/[id].tsx b/pages/shared/[id].tsx index 7f5387b03b..f5f80db4a4 100644 --- a/pages/shared/[id].tsx +++ b/pages/shared/[id].tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import { useRouter } from "next/router"; import NavigationBar from "@/components/NavigationBar"; import FolderBar from "@/components/FolderBar"; @@ -9,7 +9,6 @@ import styles from "@/styles/SharedPage.module.css"; function SharedPage() { const router = useRouter(); const { id } = router.query; - console.log(id); return (
From 6fcd2b82538402bc88973b2c4706ef77087d3ef6 Mon Sep 17 00:00:00 2001 From: beom Date: Mon, 13 May 2024 12:24:16 +0900 Subject: [PATCH 13/24] =?UTF-8?q?feat=20:=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=ED=8F=B4=EB=8D=94=EC=9D=B4=EB=A6=84=EA=B3=BC=20=EC=86=8C?= =?UTF-8?q?=EC=9C=A0=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/FolderBar.tsx | 3 +-- pages/index.tsx | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/components/FolderBar.tsx b/components/FolderBar.tsx index 68c3e0e118..988cc4e248 100644 --- a/components/FolderBar.tsx +++ b/components/FolderBar.tsx @@ -8,11 +8,10 @@ export default function FolderBar({ id }: any) { const folderInfo = useQuery({ queryKey: ["folderInfo"], queryFn: () => getFolder(id), + staleTime: 0, enabled: id !== undefined, }); - console.log(id); - //폴더 소유자를 가져오기 위한 쿼리 const folderOwner = useQuery({ queryKey: ["folderOwner"], diff --git a/pages/index.tsx b/pages/index.tsx index 1598ae06f9..a3833c75f4 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -6,9 +6,6 @@ const inter = Inter({ subsets: ["latin"] }); export default function Home() { return ( <> - -

shared/1108페이지로 이동

-

folder페이지로 이동

From e582d687479497f695ec39a6a068984408caef05 Mon Sep 17 00:00:00 2001 From: beom Date: Mon, 13 May 2024 12:26:59 +0900 Subject: [PATCH 14/24] =?UTF-8?q?feat=20:=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/modal/Share.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/components/modal/Share.tsx b/components/modal/Share.tsx index 85660fbcbf..2922c92ca2 100644 --- a/components/modal/Share.tsx +++ b/components/modal/Share.tsx @@ -17,7 +17,9 @@ export default function Share({ folderId, folderName, onClose }: ShareProps) { const router = useRouter(); const moveToSharePage = (id: number | null) => { - router.push(`/shared/${id}`); + if (id !== null) { + router.push(`/shared/${id}`); + } }; return ( @@ -41,7 +43,7 @@ export default function Share({ folderId, folderName, onClose }: ShareProps) { onClick={() => moveToSharePage(folderId)} alt="kakaoIcon" /> -

카카오톡

+

공유페이지

moveToSharePage(folderId)} alt="facebookIcon" /> -

페이스북

+

공유페이지

moveToSharePage(folderId)} alt="linkIcon" /> -

링크 복사

+

공유페이지

From ed738b2248a4f359b5a932afeef201aaffb76d82 Mon Sep 17 00:00:00 2001 From: beom Date: Mon, 13 May 2024 17:45:08 +0900 Subject: [PATCH 15/24] =?UTF-8?q?feat=20:=20[=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=EC=82=AC=ED=95=AD]=20=EB=A7=81=ED=81=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=BF=BC=EB=A6=AC=20=EC=A0=80=EC=9E=A5=20=EB=B0=8F?= =?UTF-8?q?=20api=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EC=BD=94=EB=93=9C=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 --- components/FolderSection.tsx | 16 ++++++++++++++-- components/LinkAdd.tsx | 36 ++++++++++++++++++++++++++++++++++-- pages/api/api.tsx | 26 ++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/components/FolderSection.tsx b/components/FolderSection.tsx index a15fb46c1a..e2f69d0fb7 100644 --- a/components/FolderSection.tsx +++ b/components/FolderSection.tsx @@ -2,7 +2,7 @@ import React from "react"; import Image from "next/image"; import { useEffect, useState } from "react"; import { getFolderList, getAllLinks, getFolderLink } from "@/pages/api/api"; -import { useQuery } from "@tanstack/react-query"; +import { useQuery, useQueryClient } from "@tanstack/react-query"; import CardList from "@/components/CardList"; import SearchBar from "@/components/SearchBar"; import addImg from "@/public/images/add.svg"; @@ -46,6 +46,8 @@ export default function FolderSection() { const [selectedId, setSelectedId] = useState(); const [searchInput, setSearchInput] = useState(""); + const queryClient = useQueryClient(); + //전체 폴더 가져오기 const allList = useQuery({ queryKey: ["allList"], @@ -56,6 +58,7 @@ export default function FolderSection() { async function folderAllNameClick() { setFolderName("전체"); setFolderId(null); + queryClient.setQueryData(["folderId"], null); } //개별 폴더 가져오기 @@ -75,8 +78,8 @@ export default function FolderSection() { async function folderNameClick(name: string, id: number) { setFolderName(name); setFolderId(id); + queryClient.setQueryData(["folderId"], id); } - //폴더이름을 클릭했을 때 즉각적으로 링크 데이터들이 바뀌도록 useEffect(() => { if (individualList.data && folderName !== "전체") { @@ -94,6 +97,15 @@ export default function FolderSection() { queryFn: async () => await getFolderList(), }); + //링크 추가를 위해 현재 폴더 id를 쿼리에 저장 + //처음 랜더링 될때 한번 + useQuery({ + queryKey: ["folderId"], + queryFn: async () => { + return folderId; + }, + }); + //이름변경 아이콘 클릭시 뜨는 모달창 함수 const clickEditName = () => { setIsEditNameModal(!isEditNameModal); diff --git a/components/LinkAdd.tsx b/components/LinkAdd.tsx index e0c46a4fd8..b2af6336e6 100644 --- a/components/LinkAdd.tsx +++ b/components/LinkAdd.tsx @@ -1,9 +1,37 @@ -import React from "react"; +import React, { useState } from "react"; import Image from "next/image"; +import { addLink } from "@/pages/api/api"; import styles from "@/styles/LinkAdd.module.css"; import linkIcon from "@/public/images/link.svg"; +import { useMutation, useQuery } from "@tanstack/react-query"; + +interface LinkData { + url: string; + folderId: {} | undefined; +} export default function LinkAdd() { + const [url, setUrl] = useState(""); // input 값에 대한 상태 + const folderId = useQuery({ queryKey: ["folderId"] }); + + const addLinkMutation = useMutation({ + mutationFn: (linkData) => addLink(linkData.url, Number(linkData.folderId)), + }); + + // input 값이 변경될 때마다 상태 업데이트 + const handleInputChange = (event: React.ChangeEvent) => { + setUrl(event.target.value); + }; + + // 추가하기 버튼 클릭 시 실행되는 함수 + const handleAddClick = (e: any) => { + e.preventDefault(); + //링크를 추가하는 API 호출 등의 작업 수행 + if (folderId.data !== null) { + const linkData: LinkData = { url, folderId: folderId.data }; + addLinkMutation.mutate(linkData); + } + }; return (
@@ -14,9 +42,13 @@ export default function LinkAdd() { type="text" id={styles.inputText} placeholder="링크를 추가해보세요." + value={url} // input 값과 상태를 연결 + onChange={handleInputChange} // input 값 변경 시 호출되는 함수 />
- +
diff --git a/pages/api/api.tsx b/pages/api/api.tsx index e5f45fe65c..20b43898c9 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -101,6 +101,32 @@ export async function getFolderLink(id: number) { return folderLink; } +//링크 추가를 위한 api 함수 +export async function addLink(url: string, folderId: number) { + const token = localStorage.getItem("accessToken"); + + try { + const response = await fetch(`${BASE_URL}/links`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "*/*", + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ + url: url, + folderId: folderId, + }), + }); + + if (!response.ok) { + throw new Error("링크를 추가할 수 없습니다."); + } + } catch (error) { + throw new Error("링크를 추가할 수 없습니다."); + } +} + //로그인 요청을 위한 api함수 export async function postSignIn(id: string, password: string) { const response = await fetch(`${BASE_URL}/auth/sign-in`, { From 35a8485c258ab341cb157db5d79d29188d6e5fa2 Mon Sep 17 00:00:00 2001 From: beom Date: Mon, 13 May 2024 17:52:49 +0900 Subject: [PATCH 16/24] =?UTF-8?q?feat=20:=20[=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=EC=82=AC=ED=95=AD]=20=EC=8B=A4=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EB=A7=81=ED=81=AC=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/LinkAdd.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/components/LinkAdd.tsx b/components/LinkAdd.tsx index b2af6336e6..23d5dd0178 100644 --- a/components/LinkAdd.tsx +++ b/components/LinkAdd.tsx @@ -3,7 +3,7 @@ import Image from "next/image"; import { addLink } from "@/pages/api/api"; import styles from "@/styles/LinkAdd.module.css"; import linkIcon from "@/public/images/link.svg"; -import { useMutation, useQuery } from "@tanstack/react-query"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; interface LinkData { url: string; @@ -14,8 +14,15 @@ export default function LinkAdd() { const [url, setUrl] = useState(""); // input 값에 대한 상태 const folderId = useQuery({ queryKey: ["folderId"] }); + const queryClient = useQueryClient(); + const addLinkMutation = useMutation({ mutationFn: (linkData) => addLink(linkData.url, Number(linkData.folderId)), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: ["individualList", Number(folderId.data)], + }); + }, }); // input 값이 변경될 때마다 상태 업데이트 @@ -29,7 +36,14 @@ export default function LinkAdd() { //링크를 추가하는 API 호출 등의 작업 수행 if (folderId.data !== null) { const linkData: LinkData = { url, folderId: folderId.data }; - addLinkMutation.mutate(linkData); + addLinkMutation.mutate(linkData, { + onSuccess: () => { + console.log("onSuccess in mutate"); + }, + onSettled: () => { + console.log("onSettled in mutate"); + }, + }); } }; return ( From 21c071154073a1a5cb5dab40845e0d086ed7e8be Mon Sep 17 00:00:00 2001 From: beom Date: Tue, 14 May 2024 15:00:10 +0900 Subject: [PATCH 17/24] =?UTF-8?q?feat=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/LinkAdd.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/LinkAdd.tsx b/components/LinkAdd.tsx index 23d5dd0178..2821ae6a22 100644 --- a/components/LinkAdd.tsx +++ b/components/LinkAdd.tsx @@ -40,9 +40,6 @@ export default function LinkAdd() { onSuccess: () => { console.log("onSuccess in mutate"); }, - onSettled: () => { - console.log("onSettled in mutate"); - }, }); } }; From 2d5222023462f5fb893d0deb5af173ff6776484d Mon Sep 17 00:00:00 2001 From: beom Date: Wed, 15 May 2024 16:56:17 +0900 Subject: [PATCH 18/24] =?UTF-8?q?feat=20:=20=ED=8F=B4=EB=8D=94=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EB=B3=80=EA=B2=BD=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/FolderSection.tsx | 6 ++++- components/modal/Edit.tsx | 51 +++++++++++++++++++++++++++++++++--- pages/api/api.tsx | 25 ++++++++++++++++++ 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/components/FolderSection.tsx b/components/FolderSection.tsx index e2f69d0fb7..84344d9ddd 100644 --- a/components/FolderSection.tsx +++ b/components/FolderSection.tsx @@ -151,7 +151,11 @@ export default function FolderSection() {
{isEditNameModal && ( - + )} {isAddFolderModal && } {isShareModal && ( diff --git a/components/modal/Edit.tsx b/components/modal/Edit.tsx index 939a35de2b..3cfd3c0c2b 100644 --- a/components/modal/Edit.tsx +++ b/components/modal/Edit.tsx @@ -1,14 +1,51 @@ -import React from "react"; +import React, { useState } from "react"; import Image from "next/image"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { changeName } from "@/pages/api/api"; import styles from "@/styles/Edit.module.css"; import closeIcon from "@/public/images/close.svg"; interface EditProps { + folderId: number | null; folderName: string; onClose: any; } -export default function Edit({ folderName, onClose }: EditProps) { +interface FolderData { + name: string; + folderId: number; +} + +export default function Edit({ folderId, folderName, onClose }: EditProps) { + const [name, setName] = useState(""); // input 값에 대한 상태 + const queryClient = useQueryClient(); + + // input 값이 변경될 때마다 상태 업데이트 + const handleInputChange = (event: React.ChangeEvent) => { + setName(event.target.value); + }; + + const changeFolderNameMutation = useMutation({ + mutationFn: (folderData) => + changeName(folderData.name, folderData.folderId), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: ["folderList"], + }); + }, + }); + + const clickChangeName = (name: string, folderId: number | null) => { + if (folderId) { + const folderData: FolderData = { name, folderId }; + changeFolderNameMutation.mutate(folderData, { + onSuccess: () => { + console.log("onSuccess in mutate"); + }, + }); + } + }; + return (
@@ -19,8 +56,14 @@ export default function Edit({ folderName, onClose }: EditProps) { alt="closeIcon" onClick={onClose} /> - - + +
); diff --git a/pages/api/api.tsx b/pages/api/api.tsx index 20b43898c9..d856e42763 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -127,6 +127,31 @@ export async function addLink(url: string, folderId: number) { } } +//폴더의 이름 변경을 위한 api 함수 +export async function changeName(name: string, folderId: number) { + const token = localStorage.getItem("accessToken"); + + try { + const response = await fetch(`${BASE_URL}/folders/${folderId}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + Accept: "*/*", + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ + name: name, + }), + }); + + if (!response.ok) { + throw new Error("폴더의 이름 변경을 할 수 없습니다."); + } + } catch (error) { + throw new Error("폴더의 이름 변경을 할 수 없습니다."); + } +} + //로그인 요청을 위한 api함수 export async function postSignIn(id: string, password: string) { const response = await fetch(`${BASE_URL}/auth/sign-in`, { From 85721b69162c10a858a34948285280cfc597020a Mon Sep 17 00:00:00 2001 From: beom Date: Wed, 15 May 2024 18:18:25 +0900 Subject: [PATCH 19/24] =?UTF-8?q?feat=20:=20=ED=8F=B4=EB=8D=94=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EC=9D=B4=20=ED=8F=B4=EB=8D=94=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=82=B4=EB=B6=80=EC=97=90=EC=84=9C=EB=8F=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EB=90=98=EB=8F=84=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/FolderSection.tsx | 29 +++++++++++++++++++++++------ components/modal/DeleteFolder.tsx | 2 +- components/modal/Edit.tsx | 3 ++- components/modal/Share.tsx | 2 +- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/components/FolderSection.tsx b/components/FolderSection.tsx index 84344d9ddd..53bcbd2db2 100644 --- a/components/FolderSection.tsx +++ b/components/FolderSection.tsx @@ -29,7 +29,9 @@ interface CardListType { } export default function FolderSection() { - const [folderName, setFolderName] = useState("폴더를 선택해주세요"); + const [folderName, setFolderName] = useState( + "폴더를 선택해주세요" + ); const [folderId, setFolderId] = useState(null); //카드리스트에 관한 const [cardList, setCardList] = useState([]); @@ -48,6 +50,11 @@ export default function FolderSection() { const queryClient = useQueryClient(); + //현재 폴더 이름을 최신으로 가져오기 위한 + const currentFolderName = useQuery({ + queryKey: ["folderName"], + }); + //전체 폴더 가져오기 const allList = useQuery({ queryKey: ["allList"], @@ -56,9 +63,9 @@ export default function FolderSection() { //전체 폴더 클릭 async function folderAllNameClick() { - setFolderName("전체"); setFolderId(null); queryClient.setQueryData(["folderId"], null); + queryClient.setQueryData(["folderName"], "전체"); } //개별 폴더 가져오기 @@ -76,20 +83,21 @@ export default function FolderSection() { //개별 폴더 클릭 async function folderNameClick(name: string, id: number) { - setFolderName(name); setFolderId(id); queryClient.setQueryData(["folderId"], id); + queryClient.setQueryData(["folderName"], name); } //폴더이름을 클릭했을 때 즉각적으로 링크 데이터들이 바뀌도록 useEffect(() => { - if (individualList.data && folderName !== "전체") { + setFolderName(currentFolderName.data); + if (individualList.data && currentFolderName.data !== "전체") { setCardList(individualList.data); setFilteredCardList(individualList.data); - } else if (folderName === "전체") { + } else if (currentFolderName.data === "전체") { setCardList(allList.data); setFilteredCardList(allList.data); } - }, [individualList.data, folderName, allList.data]); + }, [individualList.data, currentFolderName.data, allList.data]); //폴더 버튼 const folderList = useQuery({ @@ -106,6 +114,15 @@ export default function FolderSection() { }, }); + //폴더 이름 변경을 위해 현재 폴더 이름을 쿼리에 저장 + //처음 랜더링 될때 한번 + useQuery({ + queryKey: ["folderName"], + queryFn: async () => { + return folderName; + }, + }); + //이름변경 아이콘 클릭시 뜨는 모달창 함수 const clickEditName = () => { setIsEditNameModal(!isEditNameModal); diff --git a/components/modal/DeleteFolder.tsx b/components/modal/DeleteFolder.tsx index 55517810b9..19a1cf9634 100644 --- a/components/modal/DeleteFolder.tsx +++ b/components/modal/DeleteFolder.tsx @@ -4,7 +4,7 @@ import styles from "@/styles/DeleteFolder.module.css"; import closeIcon from "@/public/images/close.svg"; interface DeleteFolderProps { - folderName: string; + folderName: string | undefined; onClose: any; } diff --git a/components/modal/Edit.tsx b/components/modal/Edit.tsx index 3cfd3c0c2b..f102ff5974 100644 --- a/components/modal/Edit.tsx +++ b/components/modal/Edit.tsx @@ -7,7 +7,7 @@ import closeIcon from "@/public/images/close.svg"; interface EditProps { folderId: number | null; - folderName: string; + folderName: string | undefined; onClose: any; } @@ -41,6 +41,7 @@ export default function Edit({ folderId, folderName, onClose }: EditProps) { changeFolderNameMutation.mutate(folderData, { onSuccess: () => { console.log("onSuccess in mutate"); + queryClient.setQueryData(["folderName"], name); }, }); } diff --git a/components/modal/Share.tsx b/components/modal/Share.tsx index 2922c92ca2..9ead684fb2 100644 --- a/components/modal/Share.tsx +++ b/components/modal/Share.tsx @@ -9,7 +9,7 @@ import linkIcon from "@/public/images/link.svg"; interface ShareProps { folderId: number | null; - folderName: string; + folderName: string | undefined; onClose: any; } From f0f39912b513c40951ea12bede4523c9d1c22bd4 Mon Sep 17 00:00:00 2001 From: beom Date: Wed, 15 May 2024 18:28:15 +0900 Subject: [PATCH 20/24] =?UTF-8?q?feat=20:=20=ED=8F=B4=EB=8D=94=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/modal/AddFolder.tsx | 46 +++++++++++++++++++++++++++++++--- pages/api/api.tsx | 25 ++++++++++++++++++ 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/components/modal/AddFolder.tsx b/components/modal/AddFolder.tsx index 2236eefbb3..aa1cd5a37e 100644 --- a/components/modal/AddFolder.tsx +++ b/components/modal/AddFolder.tsx @@ -1,5 +1,7 @@ -import React from "react"; +import React, { useState } from "react"; import Image from "next/image"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { addFolder } from "@/pages/api/api"; import styles from "@/styles/AddFolder.module.css"; import closeIcon from "@/public/images/close.svg"; @@ -7,7 +9,39 @@ interface AddFolderProps { onClose: any; } +interface FolderData { + name: string; +} + export default function AddFolder({ onClose }: AddFolderProps) { + const [name, setName] = useState(""); // input 값에 대한 상태 + const queryClient = useQueryClient(); + + // input 값이 변경될 때마다 상태 업데이트 + const handleInputChange = (event: React.ChangeEvent) => { + setName(event.target.value); + }; + + const addFolderMutation = useMutation({ + mutationFn: (folderData) => addFolder(folderData.name), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: ["folderList"], + }); + }, + }); + + const clickChangeName = (name: string) => { + if (name) { + const folderData: FolderData = { name }; + addFolderMutation.mutate(folderData, { + onSuccess: () => { + console.log("onSuccess in mutate"); + }, + }); + } + }; + return (
@@ -18,8 +52,14 @@ export default function AddFolder({ onClose }: AddFolderProps) { alt="closeIcon" onClick={onClose} /> - - + +
); diff --git a/pages/api/api.tsx b/pages/api/api.tsx index d856e42763..75fdf87393 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -152,6 +152,31 @@ export async function changeName(name: string, folderId: number) { } } +//폴더의 추가를 위한 api 함수 +export async function addFolder(name: string) { + const token = localStorage.getItem("accessToken"); + + try { + const response = await fetch(`${BASE_URL}/folders`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "*/*", + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ + name: name, + }), + }); + + if (!response.ok) { + throw new Error("폴더를 추가할 수 없습니다."); + } + } catch (error) { + throw new Error("폴더를 추가할 수 없습니다."); + } +} + //로그인 요청을 위한 api함수 export async function postSignIn(id: string, password: string) { const response = await fetch(`${BASE_URL}/auth/sign-in`, { From 0fbacfffe3eaada0f72df31bb539498281bfda23 Mon Sep 17 00:00:00 2001 From: beom Date: Wed, 15 May 2024 18:37:20 +0900 Subject: [PATCH 21/24] =?UTF-8?q?feat=20:=20=ED=8F=B4=EB=8D=94=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/FolderSection.tsx | 6 +++++- components/modal/DeleteFolder.tsx | 34 ++++++++++++++++++++++++++++++- pages/api/api.tsx | 22 ++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/components/FolderSection.tsx b/components/FolderSection.tsx index 53bcbd2db2..238e06d677 100644 --- a/components/FolderSection.tsx +++ b/components/FolderSection.tsx @@ -183,7 +183,11 @@ export default function FolderSection() { /> )} {isDeleteFolderModal && ( - + )}
diff --git a/components/modal/DeleteFolder.tsx b/components/modal/DeleteFolder.tsx index 19a1cf9634..c8690ec218 100644 --- a/components/modal/DeleteFolder.tsx +++ b/components/modal/DeleteFolder.tsx @@ -1,17 +1,47 @@ import React from "react"; import Image from "next/image"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { deleteFolder } from "@/pages/api/api"; import styles from "@/styles/DeleteFolder.module.css"; import closeIcon from "@/public/images/close.svg"; interface DeleteFolderProps { + folderId: number | null; folderName: string | undefined; onClose: any; } +interface FolderData { + folderId: number; +} + export default function DeleteFolder({ + folderId, folderName, onClose, }: DeleteFolderProps) { + const queryClient = useQueryClient(); + + const deleteFolderMutation = useMutation({ + mutationFn: (folderData) => deleteFolder(folderData.folderId), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: ["folderList"], + }); + }, + }); + + const clickChangeName = (folderId: number | null) => { + if (folderId) { + const folderData: FolderData = { folderId }; + deleteFolderMutation.mutate(folderData, { + onSuccess: () => { + console.log("onSuccess in mutate"); + }, + }); + } + }; + return (
@@ -25,7 +55,9 @@ export default function DeleteFolder({ alt="closeIcon" onClick={onClose} /> - +
); diff --git a/pages/api/api.tsx b/pages/api/api.tsx index 75fdf87393..34fa7582c8 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -177,6 +177,28 @@ export async function addFolder(name: string) { } } +//폴더의 삭제를 위한 api 함수 +export async function deleteFolder(folderId: number) { + const token = localStorage.getItem("accessToken"); + + try { + const response = await fetch(`${BASE_URL}/folders/${folderId}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + Accept: "*/*", + Authorization: `Bearer ${token}`, + }, + }); + + if (!response.ok) { + throw new Error("폴더를 삭제할 수 없습니다."); + } + } catch (error) { + throw new Error("폴더를 삭제할 수 없습니다."); + } +} + //로그인 요청을 위한 api함수 export async function postSignIn(id: string, password: string) { const response = await fetch(`${BASE_URL}/auth/sign-in`, { From 24445a39cdd1b30aadef971c860f6f8e0e40daef Mon Sep 17 00:00:00 2001 From: beom Date: Wed, 15 May 2024 21:44:25 +0900 Subject: [PATCH 22/24] =?UTF-8?q?feat=20:=20=EB=A7=81=ED=81=AC=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=82=AD=EC=A0=9C=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/CardList.tsx | 6 ++++- components/FolderSection.tsx | 1 + components/modal/DeleteLink.tsx | 40 +++++++++++++++++++++++++++++++-- pages/api/api.tsx | 21 +++++++++++++++++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/components/CardList.tsx b/components/CardList.tsx index d533353c13..6ab8b683d6 100644 --- a/components/CardList.tsx +++ b/components/CardList.tsx @@ -7,6 +7,7 @@ import star_icon from "@/public/images/star.svg"; import kebab_icon from "@/public/images/kebab.svg"; interface CardListProps { + linkId: number; url: string; createdAt: string; desc: string; @@ -14,6 +15,7 @@ interface CardListProps { } export default function CardList({ + linkId, url, createdAt, desc, @@ -74,7 +76,9 @@ export default function CardList({ return (
- {isDeleteLinkModal && } + {isDeleteLinkModal && ( + + )} {isAddModal && } ({ + mutationFn: (linkData) => deleteLink(linkData.linkId), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: ["individualList", Number(folderId.data)], + }); + }, + }); + + const clickDeleteLink = (linkId: number) => { + if (linkId) { + const linkData: LinkData = { linkId }; + deleteFolderMutation.mutate(linkData, { + onSuccess: () => { + console.log("onSuccess in mutate"); + }, + }); + } + }; + return (
@@ -22,7 +56,9 @@ export default function DeleteFolder({ link, onClose }: DeleteLinkProps) { alt="closeIcon" onClick={onClose} /> - +
); diff --git a/pages/api/api.tsx b/pages/api/api.tsx index 34fa7582c8..8f9f4c5075 100644 --- a/pages/api/api.tsx +++ b/pages/api/api.tsx @@ -199,6 +199,27 @@ export async function deleteFolder(folderId: number) { } } +//링크 데이터의 삭제를 위한 api 함수 +export async function deleteLink(linkId: number) { + const token = localStorage.getItem("accessToken"); + + try { + const response = await fetch(`${BASE_URL}/links/${linkId}`, { + method: "DELETE", + headers: { + Accept: "*/*", + Authorization: `Bearer ${token}`, + }, + }); + + if (!response.ok) { + throw new Error("링크 데이터를 삭제할 수 없습니다."); + } + } catch (error) { + throw new Error("링크 데이터를 삭제할 수 없습니다."); + } +} + //로그인 요청을 위한 api함수 export async function postSignIn(id: string, password: string) { const response = await fetch(`${BASE_URL}/auth/sign-in`, { From 747091ff38f313fc1b89a6c7810fbe911e88cf09 Mon Sep 17 00:00:00 2001 From: beom Date: Wed, 15 May 2024 21:47:49 +0900 Subject: [PATCH 23/24] =?UTF-8?q?feat=20:=20=EA=B8=B0=EB=8A=A5=20=EC=84=B1?= =?UTF-8?q?=EA=B3=B5=EC=8B=9C=20=EB=AA=A8=EB=8B=AC=EC=B0=BD=20=EB=8B=AB?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/modal/AddFolder.tsx | 1 + components/modal/DeleteFolder.tsx | 2 ++ components/modal/Edit.tsx | 1 + 3 files changed, 4 insertions(+) diff --git a/components/modal/AddFolder.tsx b/components/modal/AddFolder.tsx index aa1cd5a37e..5f07460d03 100644 --- a/components/modal/AddFolder.tsx +++ b/components/modal/AddFolder.tsx @@ -28,6 +28,7 @@ export default function AddFolder({ onClose }: AddFolderProps) { queryClient.invalidateQueries({ queryKey: ["folderList"], }); + onClose(); }, }); diff --git a/components/modal/DeleteFolder.tsx b/components/modal/DeleteFolder.tsx index c8690ec218..ab4730afa5 100644 --- a/components/modal/DeleteFolder.tsx +++ b/components/modal/DeleteFolder.tsx @@ -28,6 +28,7 @@ export default function DeleteFolder({ queryClient.invalidateQueries({ queryKey: ["folderList"], }); + onClose(); }, }); @@ -37,6 +38,7 @@ export default function DeleteFolder({ deleteFolderMutation.mutate(folderData, { onSuccess: () => { console.log("onSuccess in mutate"); + queryClient.setQueryData(["folderName"], "폴더를 선택해주세요"); }, }); } diff --git a/components/modal/Edit.tsx b/components/modal/Edit.tsx index f102ff5974..7e44d859fe 100644 --- a/components/modal/Edit.tsx +++ b/components/modal/Edit.tsx @@ -32,6 +32,7 @@ export default function Edit({ folderId, folderName, onClose }: EditProps) { queryClient.invalidateQueries({ queryKey: ["folderList"], }); + onClose(); }, }); From abe6eee36ac8c6f82c51f91863a3fbb5343b6bc1 Mon Sep 17 00:00:00 2001 From: beom Date: Wed, 15 May 2024 21:51:52 +0900 Subject: [PATCH 24/24] =?UTF-8?q?feat=20:=20=EC=A0=84=EC=B2=B4=20=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EA=B0=80=20=EB=B0=94?= =?UTF-8?q?=EB=80=8C=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/LinkAdd.tsx | 3 +++ components/modal/DeleteLink.tsx | 3 +++ 2 files changed, 6 insertions(+) diff --git a/components/LinkAdd.tsx b/components/LinkAdd.tsx index 2821ae6a22..871c7c1a52 100644 --- a/components/LinkAdd.tsx +++ b/components/LinkAdd.tsx @@ -22,6 +22,9 @@ export default function LinkAdd() { queryClient.invalidateQueries({ queryKey: ["individualList", Number(folderId.data)], }); + queryClient.invalidateQueries({ + queryKey: ["allList"], + }); }, }); diff --git a/components/modal/DeleteLink.tsx b/components/modal/DeleteLink.tsx index 84d4bda2fc..222c498a78 100644 --- a/components/modal/DeleteLink.tsx +++ b/components/modal/DeleteLink.tsx @@ -29,6 +29,9 @@ export default function DeleteFolder({ queryClient.invalidateQueries({ queryKey: ["individualList", Number(folderId.data)], }); + queryClient.invalidateQueries({ + queryKey: ["allList"], + }); }, });