@@ -27,20 +37,31 @@ export default function Share({ folderName, onClose }: ShareProps) {
/>
-
-
카카오톡
+
moveToSharePage(folderId)}
+ alt="kakaoIcon"
+ />
+ 공유페이지
moveToSharePage(folderId)}
alt="facebookIcon"
/>
- 페이스북
+ 공유페이지
-
-
링크 복사
+
moveToSharePage(folderId)}
+ alt="linkIcon"
+ />
+ 공유페이지
diff --git a/package-lock.json b/package-lock.json
index baa2b6655..ad286bea2 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 1ce24924f..4a2f94d1f 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 8e301a9e8..994edfc89 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 7679f9237..8f9f4c507 100644
--- a/pages/api/api.tsx
+++ b/pages/api/api.tsx
@@ -1,16 +1,42 @@
-const BASE_URL = "https://bootcamp-api.codeit.kr";
+const BASE_URL = "https://bootcamp-api.codeit.kr/api/linkbrary/v1";
+//네비게이션바에 필요한 회원정보를 받아오는 api함수
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_URL}/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() {
- const response = await fetch(`${BASE_URL}/api/sample/folder`);
+//폴더 소유자의 정보를 얻기위한 api함수
+export async function getFolderUser(userId: number) {
+ const response = await fetch(`${BASE_URL}/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_URL}/folders/${id}`);
if (!response.ok) {
throw new Error("폴더 정보를 불러올 수 없습니다.");
}
@@ -18,26 +44,56 @@ export async function getFolder() {
return folder;
}
+//현재 폴더 목록들을 얻기위한 api함수
export async function getFolderList() {
- const response = await fetch(`${BASE_URL}/api/users/1/folders`);
- if (!response.ok) {
+ const token = localStorage.getItem("accessToken");
+ try {
+ const response = await fetch(`${BASE_URL}/folders`, {
+ method: "GET",
+ headers: {
+ Accept: "*/*",
+ Authorization: `Bearer ${token}`,
+ },
+ });
+
+ if (!response.ok) {
+ throw new Error("폴더 목록을 불러올 수 없습니다..");
+ }
+
+ const folderList = await response.json();
+ return folderList;
+ } catch (error) {
throw new Error("폴더 목록을 불러올 수 없습니다..");
}
- const folderList = await response.json();
- return folderList;
}
+//전체 폴더의 링크 데이터를 얻기위한 api함수
export async function getAllLinks() {
- const response = await fetch(`${BASE_URL}/api/users/1/links`);
- if (!response.ok) {
+ const token = localStorage.getItem("accessToken");
+
+ try {
+ const response = await fetch(`${BASE_URL}/links`, {
+ method: "GET",
+ headers: {
+ Accept: "*/*",
+ Authorization: `Bearer ${token}`,
+ },
+ });
+
+ if (!response.ok) {
+ throw new Error("전체 폴더 링크를 불러오는데 실패했습니다");
+ }
+
+ const allLinks = await response.json();
+ return allLinks;
+ } catch (error) {
throw new Error("전체 폴더 링크를 불러오는데 실패했습니다");
}
- const allLinks = await response.json();
- return allLinks;
}
+//개별 폴더의 링크 데이터를 얻기위한 api함수
export async function getFolderLink(id: number) {
- const response = await fetch(`${BASE_URL}/api/users/1/links?folderId=${id}`);
+ const response = await fetch(`${BASE_URL}/folders/${id}/links`);
if (!response.ok) {
throw new Error("해당 폴더 링크를 불러오는데 실패했습니다");
}
@@ -45,8 +101,128 @@ 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 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 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 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 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}/api/sign-in`, {
+ const response = await fetch(`${BASE_URL}/auth/sign-in`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
@@ -58,8 +234,9 @@ export async function postSignIn(id: string, password: string) {
return response;
}
+//이메일 중복 체크 api 함수
export async function postCheckEmail(id: string) {
- const response = await fetch(`${BASE_URL}/api/check-email`, {
+ const response = await fetch(`${BASE_URL}/users/check-email`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
@@ -70,8 +247,9 @@ export async function postCheckEmail(id: string) {
return response;
}
+//회원가입 요청을 위한 api 함수
export async function postSignUp(id: string, password: string) {
- const response = await fetch(`${BASE_URL}/api/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/folder.tsx b/pages/folder.tsx
index 202ea8b48..0a554cb82 100644
--- a/pages/folder.tsx
+++ b/pages/folder.tsx
@@ -1,4 +1,5 @@
import React from "react";
+
import NavigationBar from "@/components/NavigationBar";
import Footer from "@/components/Footer";
import LinkAdd from "@/components/LinkAdd";
diff --git a/pages/index.tsx b/pages/index.tsx
index 598a78ae0..a3833c75f 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -6,9 +6,6 @@ const inter = Inter({ subsets: ["latin"] });
export default function Home() {
return (
<>
-
-
shared페이지로 이동
-
folder페이지로 이동
diff --git a/pages/shared.tsx b/pages/shared/[id].tsx
similarity index 66%
rename from pages/shared.tsx
rename to pages/shared/[id].tsx
index 083772069..f5f80db4a 100644
--- a/pages/shared.tsx
+++ b/pages/shared/[id].tsx
@@ -1,4 +1,5 @@
-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";
import CardSection from "@/components/CardSection";
@@ -6,11 +7,13 @@ import Footer from "@/components/Footer";
import styles from "@/styles/SharedPage.module.css";
function SharedPage() {
+ const router = useRouter();
+ const { id } = router.query;
return (
-
-
+
+
);
diff --git a/pages/signin.tsx b/pages/signin.tsx
index e7bcb134a..6eb998346 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 923c68793..9189edc6a 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 {
}
}