diff --git a/components/FolderTag.tsx b/components/FolderTag.tsx index 9745c83..94b97b8 100644 --- a/components/FolderTag.tsx +++ b/components/FolderTag.tsx @@ -5,7 +5,11 @@ interface FolderData { linkCount: number; } -const FolderTag = (list: FolderData[]) => { +interface FolderTagProps { + list: FolderData[]; +} + +const FolderTag = ({ list }: FolderTagProps) => { const folderStyle = "py-[8px] px-[12px] border border-purple-100 rounded-md"; return ( diff --git a/components/Link/ActionButtons.tsx b/components/Link/ActionButtons.tsx new file mode 100644 index 0000000..b498677 --- /dev/null +++ b/components/Link/ActionButtons.tsx @@ -0,0 +1,18 @@ +import Image from "next/image"; + +const ActionButtons = () => ( +
+ {[ + { src: "/icons/share.svg", alt: "공유", text: "공유" }, + { src: "/icons/pen.svg", alt: "이름 변경", text: "이름 변경" }, + { src: "/icons/delete.svg", alt: "삭제", text: "삭제" }, + ].map(({ src, alt, text }) => ( + + ))} +
+); + +export default ActionButtons; diff --git a/pages/api/folders.ts b/pages/api/folders.ts new file mode 100644 index 0000000..d8301eb --- /dev/null +++ b/pages/api/folders.ts @@ -0,0 +1,44 @@ +import { NextApiRequest, NextApiResponse } from "next"; +import { parse } from "cookie"; +import axiosInstance from "@/lib/api/axiosInstanceApi"; + +const handler = async (req: NextApiRequest, res: NextApiResponse) => { + const cookies = parse(req.headers.cookie || ""); + const accessToken = cookies.accessToken; + + console.log("getFolder 요청 : ", accessToken); + + switch (req.method) { + case "GET": + // 유저의 모든 폴더 조회 + try { + const response = await axiosInstance.get("/folders", { + headers: { Authorization: `Bearer ${accessToken}` }, + }); + return res.status(201).json(response.data); + } catch (err) { + console.error(err); + return res + .status(500) + .json({ message: "모든 폴저 조회에 실패했습니다." }); + } + + case "POST": + // 유저의 폴더 생성 + try { + const response = await axiosInstance.post("/folders", req.body, { + headers: { Authorization: `Bearer ${accessToken}` }, + }); + return res.status(201).json(response.data); + } catch (err) { + console.error(err); + return res.status(500).json({ message: "폴더 생성에 실패했습니다." }); + } + + default: + res.setHeader("Allow", ["GET", "POST"]); + return res.status(405).end(`메서드 ${req.method}는 허용되지 않습니다.`); + } +}; + +export default handler; diff --git a/pages/api/links.ts b/pages/api/links.ts new file mode 100644 index 0000000..53f0128 --- /dev/null +++ b/pages/api/links.ts @@ -0,0 +1,46 @@ +import { NextApiRequest, NextApiResponse } from "next"; +import { parse } from "cookie"; +import axiosInstance from "@/lib/api/axiosInstanceApi"; + +const handler = async (req: NextApiRequest, res: NextApiResponse) => { + const cookies = parse(req.headers.cookie || ""); + const accessToken = cookies.accessToken; + + console.log("서버에서 전달받은 쿠키의 값: ", cookies); + console.log("서버에서 전달받은 토큰의 값: ", accessToken); + + switch (req.method) { + case "GET": + // 유저의 전체 링크 조회 + try { + + const response = await axiosInstance.get("/links", { + headers: { Authorization: `Bearer ${accessToken}` }, + }); + return res.status(201).json(response.data); + } catch (err) { + console.error(err); + return res + .status(500) + .json({ message: "전체 링크 조회에 실패했습니다." }); + } + + case "POST": + // 링크 생성 로직 + try { + const response = await axiosInstance.post("/links", req.body, { + headers: { Authorization: `Bearer ${accessToken}` }, + }); + return res.status(201).json(response.data); + } catch (err) { + console.error(err); + return res.status(500).json({ message: "링크 생성에 실패했습니다." }); + } + + default: + res.setHeader("Allow", ["GET", "POST"]); + return res.status(405).end(`메서드 ${req.method}는 허용되지 않습니다.`); + } +}; + +export default handler; diff --git a/pages/link/index.tsx b/pages/link/index.tsx new file mode 100644 index 0000000..51a84f9 --- /dev/null +++ b/pages/link/index.tsx @@ -0,0 +1,74 @@ +import { GetServerSidePropsContext } from "next"; +import { proxy } from "@/lib/api/axiosInstanceApi"; +import { SearchInput } from "../../components/Search/SearchInput"; +import { LinkData } from "@/types/linkTypes"; +import { FolderData } from "@/types/folderTypes"; +import Container from "@/components/Layout/Container"; +import CardsLayout from "@/components/Layout/CardsLayout"; +import FolderTag from "../../components/FolderTag"; +import LinkCard from "../../components/LinkCard"; +import AddLinkInput from "@/components/link/AddLinkInput"; +import ActionButtons from "@/components/link/ActionButtons"; + +interface LinkPageProps { + links: LinkData[]; + folders: FolderData[]; +} +export const getServerSideProps = async ( + context: GetServerSidePropsContext +) => { + const { req } = context; + + const fetchData = async (endpoint: string) => { + const response = await proxy.get(endpoint, { + headers: { + Cookie: req.headers.cookie, + }, + }); + return response.data; + }; + + const [links, folders] = await Promise.all([ + fetchData("/api/links"), + fetchData("/api/folders"), + ]); + + return { + props: { + links: links.list || [], // 기본값 처리 + folders: folders || [], // 기본값 처리 + }, + }; +}; + +const LinkPage = ({ links, folders }: LinkPageProps) => { + return ( + <> +
+ +
+
+ + +
+ + +
+
+

유용한 글

+ +
+ + {links.map((link) => ( + + ))} + +
+
+ + ); +}; + +export default LinkPage; diff --git a/public/icons/delete.svg b/public/icons/delete.svg new file mode 100644 index 0000000..1923de9 --- /dev/null +++ b/public/icons/delete.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/icons/pen.svg b/public/icons/pen.svg new file mode 100644 index 0000000..fb75fc3 --- /dev/null +++ b/public/icons/pen.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/share.svg b/public/icons/share.svg new file mode 100644 index 0000000..da9d0c1 --- /dev/null +++ b/public/icons/share.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/types/folderTypes.ts b/types/folderTypes.ts new file mode 100644 index 0000000..8db6c6d --- /dev/null +++ b/types/folderTypes.ts @@ -0,0 +1,6 @@ +export interface FolderData { + id: number; + createdAt: string; + name: string; + linkCount: number; +} diff --git a/types/linkTypes.ts b/types/linkTypes.ts new file mode 100644 index 0000000..96088c6 --- /dev/null +++ b/types/linkTypes.ts @@ -0,0 +1,9 @@ +export interface LinkData { + id: number; + favorite: boolean; + url: string; + title: string; + imageSource: string; + description: string; + createdAt: string; +}