diff --git a/src/api/article.ts b/src/api/article.ts index 02f9f01..aa2acb4 100644 --- a/src/api/article.ts +++ b/src/api/article.ts @@ -38,3 +38,29 @@ export const uploadImage = async (imageUrl: string) => { throw new Error('api Error'); } }; + +export const getArticleList = async ( + type: string, + category: string, + page: number, +) => { + try { + const token = localStorage.getItem('token'); + if (!token) { + throw new Error('로그인이 필요합니다.'); + } + + const url = `/contents/list?type=${type}&category=${category}&page=${page}`; + + const { data } = await apiClient.get(url, { + headers: { + Authorization: `${token}`, + }, + }); + + return data; + } catch (error) { + console.error(error); + throw new Error('API Error'); + } +}; diff --git a/src/components/editor/common/link.ts b/src/components/editor/common/link.ts index 4baea1b..85563cb 100644 --- a/src/components/editor/common/link.ts +++ b/src/components/editor/common/link.ts @@ -20,6 +20,12 @@ export const createLinkNodeHTML = (attrs: LinkAttributes): HTMLElement => { ) { formattedUrl = 'https://' + formattedUrl; } + try { + const url = new URL(formattedUrl); + formattedUrl = url.hostname; + } catch (err) { + console.error("Invalid URL:", formattedUrl, err); + } if (attrs.type === 'imageLink') { if (attrs.thumbnail) { @@ -64,7 +70,7 @@ export const createLinkNodeHTML = (attrs: LinkAttributes): HTMLElement => { summaryElement.textContent = attrs.summary; const urlElement = document.createElement('p'); - urlElement.className = 'mt-[9px] text-[12px] text-sky-600 no-underline'; + urlElement.className = 'mt-[9px] text-[12px] text-sky-600 no-underline truncate'; urlElement.textContent = formattedUrl; textWrapper.appendChild(titleElement); @@ -122,7 +128,7 @@ export const createLinkNodeHTML = (attrs: LinkAttributes): HTMLElement => { const urlElement = document.createElement('p'); urlElement.className = - 'mt-[9px] text-sky-600 text-[13px] break-all whitespace-nowrap overflow-hidden text-ellipsis no-underline'; + 'mt-[9px] text-sky-600 text-[13px] no-underline truncate'; urlElement.textContent = formattedUrl; textWrapper.appendChild(titleElement); @@ -155,7 +161,7 @@ export const createLinkNodeHTML = (attrs: LinkAttributes): HTMLElement => { summaryElement.textContent = attrs.summary; const urlElement = document.createElement('p'); - urlElement.className = 'text-[12px] text-sky-600 mt-[9px] no-underline'; + urlElement.className = 'text-[12px] text-sky-600 mt-[9px] no-underline truncate'; urlElement.textContent = formattedUrl; textWrapper.appendChild(titleElement); diff --git a/src/components/editor/customComponent/CustomBlockLink.ts b/src/components/editor/customComponent/CustomBlockLink.ts index e2d04d5..cb3d371 100644 --- a/src/components/editor/customComponent/CustomBlockLink.ts +++ b/src/components/editor/customComponent/CustomBlockLink.ts @@ -83,7 +83,7 @@ const CustomBlockLink = Node.create({ [ 'p', { - class: 'text-[12px] text-[#a1885f] underline', + class: 'text-[12px] text-[#a1885f] no-underline truncate', }, HTMLAttributes.url, ], diff --git a/src/components/editor/customComponent/CustomLink.ts b/src/components/editor/customComponent/CustomLink.ts index 8905f55..20446fe 100644 --- a/src/components/editor/customComponent/CustomLink.ts +++ b/src/components/editor/customComponent/CustomLink.ts @@ -139,7 +139,7 @@ const CustomLink = Node.create({ 'p', { class: - 'whitespace-nowrap overflow-hidden text-ellipsis break-all mt-[9px] text-[#a1885f] text-[13px] no-underline', + 'mt-[9px] text-[#a1885f] text-[13px] no-underline truncate', }, HTMLAttributes.url, ], diff --git a/src/components/editor/customComponent/CustomOgLink.ts b/src/components/editor/customComponent/CustomOgLink.ts index 4a0457f..92bc5f3 100644 --- a/src/components/editor/customComponent/CustomOgLink.ts +++ b/src/components/editor/customComponent/CustomOgLink.ts @@ -140,7 +140,7 @@ const CustomOgLink = Node.create({ 'p', { class: - 'mt-[9px] text-[#a1885f] text-[13px] break-all whitespace-nowrap overflow-hidden text-ellipsis no-underline', + 'mt-[9px] text-[#a1885f] text-[13px] no-underline truncate', }, HTMLAttributes.url, ], diff --git a/src/components/editor/customComponent/CustomVerticalLink.ts b/src/components/editor/customComponent/CustomVerticalLink.ts index 544b044..4ab8305 100644 --- a/src/components/editor/customComponent/CustomVerticalLink.ts +++ b/src/components/editor/customComponent/CustomVerticalLink.ts @@ -81,7 +81,7 @@ const CustomVerticalLink = Node.create({ [ 'p', { - class: 'text-[12px] text-[#a1885f] no-underline', + class: 'text-[12px] text-[#a1885f] no-underline truncate', }, HTMLAttributes.url, ], diff --git a/src/pages/HomPage.tsx b/src/pages/HomPage.tsx index 0918061..86a323b 100644 --- a/src/pages/HomPage.tsx +++ b/src/pages/HomPage.tsx @@ -1,44 +1,83 @@ -import React from "react"; +import React, { useEffect, useState } from 'react'; +import { ArticleContent } from '../types/article'; +import { getArticleList } from '../api/article'; +import ArticlePagination from './pagenation'; + +// 날짜 변환 함수 (YYYY-MM-DD) +const formatDate = (dateString: string) => { + const date = new Date(dateString); + return `${date.getFullYear()}년 ${date.getMonth() + 1}월 ${date.getDate()}일`; +}; + +// type (article -> 아티클, video -> 영상, all -> 전체) +const typeToName = (type: string) => { + if (type === 'article') return '아티클'; + if (type === 'video') return '영상'; + return '전체'; +}; const HomePage: React.FC = () => { - const bookmarks = [ - { - id: 1, - title: "오래된 아이템...", - date: "2024-06-06", - category: "가구 장식", - }, - { - id: 2, - title: "또다른 오래된...", - date: "2024-06-05", - category: "가구 장식", - }, - ]; + const [articles, setArticles] = useState([]); + const [page, setPage] = useState(1); + const [size] = useState(5); + const [totalPages, setTotalPages] = useState(1); + + useEffect(() => { + const fetchArticles = async () => { + const type = 'all'; + const category = 'all'; + const response = await getArticleList(type, category, page); + setArticles(response.content); + setTotalPages(Math.ceil(response.total / size)); + }; + + fetchArticles(); + }, [page, size]); + + const handlePageChange = (newPage: number) => { + if (newPage >= 1 && newPage <= totalPages) { + setPage(newPage); + } + }; return (
북마크
-
찜한 콘텐츠 {bookmarks.length}
+
찜한 콘텐츠 {articles.length}
- {bookmarks.map((bookmark) => ( + {articles.map((items) => (
-
+
+ {items.article.title} +
-
- {bookmark.title} +
+ {items.article.title} +
+
+ {typeToName(items.article.type)} +
+
+ {formatDate(items.article.date)}
-
{bookmark.category}
-
{bookmark.date}
))}
+ +
); }; diff --git a/src/pages/pagenation.tsx b/src/pages/pagenation.tsx new file mode 100644 index 0000000..65790e3 --- /dev/null +++ b/src/pages/pagenation.tsx @@ -0,0 +1,89 @@ +import React, { useState, useEffect } from 'react'; + +interface PaginationProps { + totalPages: number; + onPageChange: (page: number) => void; // 페이지 변경 시 부모 컴포넌트에서 처리 가능 +} + +const ArticlePagination: React.FC = ({ + totalPages, + onPageChange, +}) => { + const [currentPage, setCurrentPage] = useState(1); + const [pageNumbers, setPageNumbers] = useState([]); + const [currentRange, setCurrentRange] = useState(0); + + useEffect(() => { + // 현재 페이지가 속한 그룹(5개 단위) 계산 + const range = Math.floor((currentPage - 1) / 5); + setCurrentRange(range); + }, [currentPage]); + + useEffect(() => { + // 현재 그룹의 페이지 목록 생성 (5개씩) + const start = currentRange * 5 + 1; + const end = Math.min(start + 4, totalPages); + const pages: number[] = Array.from( + { length: end - start + 1 }, + (_, i) => start + i, + ); + setPageNumbers(pages); + }, [currentRange, totalPages]); + + const handlePageClick = (page: number) => { + setCurrentPage(page); + onPageChange(page); // 부모 컴포넌트에서 데이터 요청 가능 + }; + + const handleNextRange = () => { + if ((currentRange + 1) * 5 < totalPages) { + const newRange = currentRange + 1; + setCurrentRange(newRange); + handlePageClick(newRange * 5 + 1); // 다음 그룹의 첫 번째 페이지로 이동 + } + }; + + const handlePrevRange = () => { + if (currentRange > 0) { + const newRange = currentRange - 1; + setCurrentRange(newRange); + handlePageClick(newRange * 5 + 1); // 이전 그룹의 첫 번째 페이지로 이동 + } + }; + + return ( +
+ + + {pageNumbers.map((page) => ( + + ))} + + +
+ ); +}; + +export default ArticlePagination; diff --git a/src/types/article.ts b/src/types/article.ts index 49329cb..d025328 100644 --- a/src/types/article.ts +++ b/src/types/article.ts @@ -7,4 +7,24 @@ export interface AddArticleData { imageLink: string; paywallUp: string; paywallDown: string; -} \ No newline at end of file +} + +export interface Article { + articleId: number; + title: string; + date: string; + type: string; + img_link?: string; +} + +export interface ArticleContent { + likedByMe: boolean; + article: Article; +} + +export interface ListArticleData { + total: number; + size: number; + page: number; + content: ArticleContent[]; +}