diff --git a/contexts/UserInfoContext.tsx b/contexts/UserInfoContext.tsx
new file mode 100644
index 000000000..44c4f8af2
--- /dev/null
+++ b/contexts/UserInfoContext.tsx
@@ -0,0 +1,19 @@
+import React, { createContext, useState, useContext } from 'react';
+
+interface Props {
+ children: React.ReactNode;
+}
+
+const UserInfoContext = createContext
(undefined);
+
+export const UserInfoProvider = ({ children }: Props) => {
+ const [userInfo, setUserInfo] = useState(null);
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useUserInfo = () => useContext(UserInfoContext);
diff --git a/next.config.js b/next.config.js
index a843cbee0..7d57d06ad 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,6 +1,14 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
-}
+ images: {
+ remotePatterns: [
+ {
+ protocol: 'https',
+ hostname: '**',
+ },
+ ],
+ },
+};
-module.exports = nextConfig
+module.exports = nextConfig;
diff --git a/package-lock.json b/package-lock.json
index 7291ba208..9d6193a23 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@hookform/resolvers": "^3.3.4",
+ "axios": "^1.6.8",
"next": "13.5.6",
"react": "^18",
"react-dom": "^18",
@@ -730,6 +731,11 @@
"has-symbols": "^1.0.3"
}
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
"node_modules/available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
@@ -751,6 +757,16 @@
"node": ">=4"
}
},
+ "node_modules/axios": {
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz",
+ "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/axobject-query": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
@@ -928,6 +944,17 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -1014,6 +1041,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -1718,6 +1753,25 @@
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
"dev": true
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
@@ -1727,6 +1781,19 @@
"is-callable": "^1.1.3"
}
},
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -2606,6 +2673,25 @@
"node": ">=8.6"
}
},
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -3002,6 +3088,11 @@
"react-is": "^16.13.1"
}
},
+ "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=="
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
diff --git a/package.json b/package.json
index 8ce47dbb0..9d1d65076 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
},
"dependencies": {
"@hookform/resolvers": "^3.3.4",
+ "axios": "^1.6.8",
"next": "13.5.6",
"react": "^18",
"react-dom": "^18",
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 414555e40..a75faeba6 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -1,6 +1,7 @@
import '@/styles/reset.css';
import '@/styles/globals.css';
import type { AppProps } from 'next/app';
+import { UserInfoProvider } from '@/contexts/UserInfoContext';
import Header from '@/components/Header/Header';
import Footer from '@/components/Footer/Footer';
@@ -8,16 +9,18 @@ export default function App({ Component, pageProps }: AppProps) {
const isAuthPage = Component.name === 'SignIn' || Component.name === 'SignUp';
return (
- <>
- {isAuthPage ? (
-
- ) : (
- <>
-
+
+ <>
+ {isAuthPage ? (
-
- >
- )}
- >
+ ) : (
+ <>
+
+
+
+ >
+ )}
+ >
+
);
}
diff --git a/pages/_document.tsx b/pages/_document.tsx
index 54e8bf3e2..55ad65786 100644
--- a/pages/_document.tsx
+++ b/pages/_document.tsx
@@ -1,13 +1,18 @@
-import { Html, Head, Main, NextScript } from 'next/document'
+import { Html, Head, Main, NextScript } from 'next/document';
export default function Document() {
return (
-
+
+
- )
+ );
}
diff --git a/pages/folder/index.tsx b/pages/folder/index.tsx
new file mode 100644
index 000000000..12309f765
--- /dev/null
+++ b/pages/folder/index.tsx
@@ -0,0 +1,184 @@
+import LinkCardList from '@/components/LinkCardList/LinkCardList';
+import { useUserInfo } from '@/contexts/UserInfoContext';
+import { axiosInstance } from '@/utils/axiosInstance';
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+import { FolderObj, LinkObj } from '@/utils/interfaces';
+import Modal from '@/components/Modal/Modal';
+import styles from '@/styles/FolderPage.module.scss';
+import {
+ DeleteModal,
+ FolderInputModal,
+ ShareModal,
+ AddToFolderModal,
+} from '@/components/ModalContents';
+
+const allFolder = {
+ id: -1,
+ name: '전체',
+ user_id: -1,
+};
+
+export default function Folder() {
+ const [currentFolderId, setCurrentFolderId] = useState(-1);
+ const { userInfo, setUserInfo } = useUserInfo();
+ const [folders, setFolders] = useState
([]);
+ const [links, setLinks] = useState();
+ const [showModal, setShowModal] = useState(false);
+ const [modalContent, setModalContent] = useState(
+ null
+ );
+ const router = useRouter();
+
+ const loadUser = async () => {
+ const accessToken = localStorage.getItem('accessToken');
+ if (!accessToken) {
+ router.push('/signin');
+ }
+ const response = await axiosInstance.get('/users', {
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ },
+ });
+ setUserInfo(response.data.data[0]);
+ setCurrentFolderId(-1);
+ };
+
+ const getUserFolders = async () => {
+ if (userInfo) {
+ const response = await axiosInstance.get(`/users/${userInfo.id}/folders`);
+ allFolder.user_id = userInfo.id;
+ setFolders([allFolder, ...response.data.data]);
+ }
+ };
+
+ const getUserLinks = async (folderId?: number) => {
+ if (userInfo) {
+ const folderEndPoint =
+ folderId && folderId !== -1 ? `?folderId=${folderId}` : '';
+ const response = await axiosInstance.get(
+ `/users/${userInfo.id}/links${folderEndPoint}`
+ );
+ setLinks(response.data.data);
+ }
+ };
+
+ const handleFolderAddClick = () => {
+ setShowModal(true);
+ setModalContent(
+
+ );
+ };
+
+ const handleFolderNameChangeClick = () => {
+ const currentFolder = folders.find(
+ (folder) => folder.id === currentFolderId
+ );
+ if (!currentFolder) return;
+ setShowModal(true);
+ setModalContent(
+
+ );
+ };
+
+ const handleFolderDeleteClick = () => {
+ const currentFolder = folders.find(
+ (folder) => folder.id === currentFolderId
+ );
+ if (!currentFolder) return;
+ setShowModal(true);
+ setModalContent(
+
+ );
+ };
+
+ const handleLinkDeleteClick = (link: string) => {
+ setShowModal(true);
+
+ setModalContent(
+
+ );
+ };
+
+ const handleAddToFolder = (link: string) => {
+ setShowModal(true);
+ setModalContent(
+
+ );
+ };
+
+ const handleShareClick = () => {
+ const currentFolder = folders.find(
+ (folder) => folder.id === currentFolderId
+ );
+ if (!currentFolder) return;
+ setShowModal(true);
+ setModalContent(
+
+ );
+ };
+
+ const handleFolderNameButtonClick = async (id: number) => {
+ setCurrentFolderId(id);
+ let result;
+ try {
+ result = await getUserLinks(id);
+ } catch (error) {
+ return;
+ }
+ };
+
+ useEffect(() => {
+ loadUser();
+ }, []);
+
+ useEffect(() => {
+ getUserFolders();
+ getUserLinks();
+ console.log(folders);
+ console.log(links);
+ }, [userInfo]);
+
+ return (
+ <>
+ {' '}
+ {showModal && (
+ <>
+ setShowModal(false)}>{modalContent}
+ setShowModal(false)}
+ >
+ >
+ )}
+
+ >
+ );
+}
diff --git a/pages/index.tsx b/pages/index.tsx
index e71579f85..4592e5eab 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -4,14 +4,16 @@ import styles from '@/styles/Home.module.css';
import Button from '@/components/Button/Button';
import Image from 'next/image';
import { useRouter } from 'next/router';
+import { useUserInfo } from '@/contexts/UserInfoContext';
const inter = Inter({ subsets: ['latin'] });
export default function Home() {
const router = useRouter(); // Access the router object
-
+ const { userInfo } = useUserInfo();
const handleAddLinkClick = () => {
- router.push('/signup'); // Navigate to /signup route when button is clicked
+ userInfo ? router.push('/folder') : router.push('/signup'); // Navigate to /signup route when button is clicked
+
};
return (
@@ -38,6 +40,7 @@ export default function Home() {
fill
alt='Page Example Image'
/>
+