diff --git a/components/Link/LinkCard.tsx b/components/Link/LinkCard.tsx index 31abdf7..4eb9e07 100644 --- a/components/Link/LinkCard.tsx +++ b/components/Link/LinkCard.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from "react"; import { useRouter } from "next/router"; import { putLinkFavorite } from "@/lib/api/link"; import { useLinkCardStore } from "@/store/useLinkCardStore"; +import { ensureAbsoluteUrl } from "@/lib/utils"; import timeAgo from "@/util/timAgo"; import Image from "next/image"; import Dropdown from "../Dropdown"; @@ -73,7 +74,7 @@ const LinkCard = ({ info }: LinkCardProps) => {
링크 미리보기 = ({ totalCount }) => { - const router = useRouter(); const LiStyle = "relative w-12 h-12 rounded-lg bg-gray900"; - const buttonStyle = "flex justify-center items-center h-full text-black400"; - const { page, pageSize } = router.query; + const buttonStyle = + "flex justify-center items-center w-full h-full text-black400"; + + const router = useRouter(); - const currentPage = Number(page); - const currentPageSize = Number(pageSize); + const { page, pageSize } = router.query; + const currentPage = Number(page) || 1; + const currentPageSize = Number(pageSize) || 6; const totalPages = Math.ceil(totalCount / currentPageSize); - const [maxPagesToShow, setMaxPagesToShow] = useState(2); - // 화면 크기 변화에 따라 pageSize와 maxPagesToShow를 설정 - useEffect(() => { - const handleResize = () => { - const width = window.innerWidth; - setMaxPagesToShow(width > 1024 ? 5 : 3); - }; + const [maxPagesToShow, setMaxPagesToShow] = useState(2); + const { isPC } = useViewport(); - // 초기 설정 및 리사이즈 이벤트 리스너 추가 - handleResize(); - window.addEventListener("resize", handleResize); + const handlePageChange = (newPage: number) => { + if (newPage !== currentPage) { + const path = router.pathname; + router.push( + { + pathname: path, + query: { page: newPage, pageSize: currentPageSize }, + }, + undefined, + { shallow: true } + ); + } + }; - return () => { - window.removeEventListener("resize", handleResize); - }; - }, []); + // 화면 크기 변화에 따라 maxPagesToShow를 설정 + useEffect(() => { + if (isPC) { + setMaxPagesToShow(5); + } else { + setMaxPagesToShow(3); + } + }, [isPC]); // 페이지 리스트 생성 함수 const getPageNumbers = () => { @@ -59,9 +70,10 @@ const Pagination: React.FC = ({ totalCount }) => { return (
  • - handlePageChange(currentPage - 1)} className={`${buttonStyle} ${currentPage > 1 ? "text-black500" : "pointer-events-none"}`} + disabled={currentPage <= 1} > = ({ totalCount }) => { width={24} alt="prev" /> - +
  • {/* 페이지 번호와 생략 표시 */} {getPageNumbers().map((pageNum, index) => typeof pageNum === "number" ? (
  • - handlePageChange(pageNum)} className={`${buttonStyle} ${pageNum === currentPage ? "text-black500" : "text-black400"}`} > {pageNum} - +
  • ) : (
  • = ({ totalCount }) => { )}
  • - handlePageChange(currentPage + 1)} className={`${buttonStyle} ${currentPage < totalPages ? "text-black500" : "pointer-events-none"}`} + disabled={currentPage >= totalPages} > = ({ totalCount }) => { height={24} alt="next" /> - +
); diff --git a/hooks/useFetchLinks.tsx b/hooks/useFetchLinks.tsx index c01b4af..679b18e 100644 --- a/hooks/useFetchLinks.tsx +++ b/hooks/useFetchLinks.tsx @@ -1,7 +1,7 @@ -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { proxy } from "@/lib/api/axiosInstanceApi"; import { LinkData } from "@/types/linkTypes"; -import useViewport from "./useViewport"; +import { useRouter } from "next/router"; // 링크페이지의 query가 바뀌면 새로운 리스트로 업데이트 해주는 훅 const useFetchLinks = ( @@ -11,22 +11,32 @@ const useFetchLinks = ( }, setLinkCardList: (list: LinkData[]) => void ) => { - const { isTablet } = useViewport(); + const router = useRouter(); useEffect(() => { const fetchLinks = async () => { - const res = await proxy.get("/api/links", { - params: { - page: query.page, - pageSize: isTablet ? 6 : 10, - search: query.search, - }, - }); - setLinkCardList(res.data.list); + // 경로에 따라 API 엔드포인트 분기 + let endpoint = "/api/links"; + const params: any = { + page: query.page, + pageSize: 6, + search: query.search, + }; + + if (router.pathname === "/favorite") { + endpoint = "/api/favorites"; + } + + try { + const res = await proxy.get(endpoint, { params }); + setLinkCardList(res.data.list); + } catch (error) { + console.error("Error fetching links:", error); + } }; if (query) fetchLinks(); - }, [query, setLinkCardList, isTablet]); + }, [query, setLinkCardList, router.pathname]); }; export default useFetchLinks; diff --git a/lib/utils.ts b/lib/utils.ts index acb5cf9..51ab41d 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -2,3 +2,8 @@ export const bindCls = (...cls: string[]) => { return cls.join(" "); }; + +// 데이터나 API에서 이미지 URL이 //로 오는 경우 자동으로 프로토콜 추가 +export const ensureAbsoluteUrl = (url: string) => { + return url.startsWith("//") ? `https:${url}` : url; +}; diff --git a/pages/api/favorites/index.ts b/pages/api/favorites/index.ts index b333ac5..ae77005 100644 --- a/pages/api/favorites/index.ts +++ b/pages/api/favorites/index.ts @@ -5,6 +5,7 @@ import axiosInstance from "@/lib/api/axiosInstanceApi"; const handler = async (req: NextApiRequest, res: NextApiResponse) => { const cookies = parse(req.headers.cookie || ""); const accessToken = cookies.accessToken; + const { page, pageSize = 6 } = req.query; if (!accessToken) { return res.status(401).json({ message: "인증 오류: 토큰이 없습니다." }); @@ -14,12 +15,10 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { case "GET": // 즐겨찾기 목록 조회 try { - const response = await axiosInstance.get( - "/favorites?page=1&pageSize=10", - { - headers: { Authorization: `Bearer ${accessToken}` }, - } - ); + const response = await axiosInstance.get(`/favorites`, { + params: { page, pageSize }, + headers: { Authorization: `Bearer ${accessToken}` }, + }); return res.status(200).json(response.data); } catch (err: any) { // 즐겨찾기 폴더가 없는 경우 (404 처리) diff --git a/pages/api/links/index.ts b/pages/api/links/index.ts index bfc13d2..bd3bd4b 100644 --- a/pages/api/links/index.ts +++ b/pages/api/links/index.ts @@ -5,7 +5,7 @@ import axiosInstance from "@/lib/api/axiosInstanceApi"; const handler = async (req: NextApiRequest, res: NextApiResponse) => { const cookies = parse(req.headers.cookie || ""); const accessToken = cookies.accessToken; - const { page, pageSize, search } = req.query; + const { page, pageSize = 6, search } = req.query; switch (req.method) { case "GET": diff --git a/pages/favorite/index.tsx b/pages/favorite/index.tsx index c1e9861..f942be3 100644 --- a/pages/favorite/index.tsx +++ b/pages/favorite/index.tsx @@ -1,8 +1,13 @@ import { GetServerSideProps, GetServerSidePropsContext } from "next"; -import { proxy } from "@/lib/api/axiosInstanceApi"; +import axiosInstance from "@/lib/api/axiosInstanceApi"; import CardsLayout from "@/components/Layout/CardsLayout"; import Container from "@/components/Layout/Container"; import LinkCard from "@/components/Link/LinkCard"; +import Pagination from "@/components/Pagination"; +import useFetchLinks from "@/hooks/useFetchLinks"; +import { useRouter } from "next/router"; +import { useState } from "react"; +import { parse } from "cookie"; interface FavoriteDataType { id: number; @@ -24,13 +29,11 @@ export const getServerSideProps: GetServerSideProps = async ( ) => { // 클라이언트의 쿠키 가져오기 const { req } = context; - const cookies = req.headers.cookie || ""; - + const cookies = parse(req.headers.cookie || ""); + const accessToken = cookies.accessToken; try { - const res = await proxy.get("/api/favorites", { - headers: { - Cookie: cookies, - }, + const res = await axiosInstance.get("/favorites?page=1&pageSize=10", { + headers: { Authorization: `Bearer ${accessToken}` }, }); const { list, totalCount } = res.data || { list: [], totalCount: 0 }; @@ -42,6 +45,12 @@ export const getServerSideProps: GetServerSideProps = async ( }; const FavoritePage = ({ favoriteList, totalCount }: FavoriteProps) => { + const router = useRouter(); + + const [linkCardList, setLinkCardList] = + useState(favoriteList); + + useFetchLinks(router.query, setLinkCardList); return ( <>
@@ -51,8 +60,8 @@ const FavoritePage = ({ favoriteList, totalCount }: FavoriteProps) => {
- {favoriteList.length > 0 - ? favoriteList.map((favorite) => ( + {linkCardList.length > 0 + ? linkCardList.map((favorite) => ( )) : null} @@ -70,6 +79,7 @@ const FavoritePage = ({ favoriteList, totalCount }: FavoriteProps) => {
)} + );