diff --git a/.vscode/launch.json b/.vscode/launch.json index 9c243a03..598ee3d8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,7 +1,4 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { diff --git a/api/articleApi.ts b/api/articleApi.ts new file mode 100644 index 00000000..8f4c6a70 --- /dev/null +++ b/api/articleApi.ts @@ -0,0 +1,50 @@ +export async function getArticleDetail(articleId: number) { + if (!articleId) { + throw new Error("Invalid article ID"); + } + + try { + const response = await fetch( + `https://panda-market-api.vercel.app/articles/${articleId}` + ); + if (!response.ok) { + throw new Error(`HTTP error: ${response.status}`); + } + const body = await response.json(); + return body; + } catch (error) { + console.error("Failed to fetch article detail:", error); + throw error; + } +} + +export async function getArticleComments({ + articleId, + limit = 10, +}: { + articleId: number; + limit?: number; +}) { + if (!articleId) { + throw new Error("Invalid article ID"); + } + + const params = { + limit: String(limit), + }; + + try { + const query = new URLSearchParams(params).toString(); + const response = await fetch( + `https://panda-market-api.vercel.app/articles/${articleId}/comments?${query}` + ); + if (!response.ok) { + throw new Error(`HTTP error: ${response.status}`); + } + const body = await response.json(); + return body; + } catch (error) { + console.error("Failed to fetch article comments:", error); + throw error; + } +} diff --git a/api/example.http b/api/example.http new file mode 100644 index 00000000..39f249f6 --- /dev/null +++ b/api/example.http @@ -0,0 +1,8 @@ +GET https://panda-market-api.vercel.app/articles + +### + +GET https://panda-market-api.vercel.app/articles?orderBy=like&pageSize=10&page=1 + +### + diff --git a/components/boards/AllArticlesSection.tsx b/components/board/AllArticlesSection.tsx similarity index 81% rename from components/boards/AllArticlesSection.tsx rename to components/board/AllArticlesSection.tsx index 8d5027dc..d0005135 100644 --- a/components/boards/AllArticlesSection.tsx +++ b/components/board/AllArticlesSection.tsx @@ -1,5 +1,5 @@ +import styled from "styled-components"; import { - FlexRowCentered, LineDivider, SectionHeader, SectionTitle, @@ -7,34 +7,32 @@ import { } from "@/styles/CommonStyles"; import { Article, ArticleSortOption } from "@/types/articleTypes"; import { - ArticleInfo, + ArticleInfoWrapper, ArticleThumbnail, ArticleTitle, ImageWrapper, MainContent, - Timestamp, -} from "@/styles/BoardsStyles"; +} from "@/styles/BoardStyles"; import Image from "next/image"; -import { format } from "date-fns"; +import Link from "next/link"; import SearchBar from "@/components/ui/SearchBar"; import DropdownMenu from "@/components/ui/DropdownMenu"; import { useEffect, useState } from "react"; import LikeCountDisplay from "@/components/ui/LikeCountDisplay"; import EmptyState from "@/components/ui/EmptyState"; import { useRouter } from "next/router"; +import ArticleInfo from "@/components/board/ArticleInfo"; -import { ItemContainer, ArticleInfoDiv, AddArticleLink } from "./AllArticlesSection.styles"; +const ItemContainer = styled(Link)``; -type ArticleItemProps = { +interface ArticleItemProps { article: Article; } -const ArticleItem = ({ article }: ArticleItemProps) => { - const dateString = format(article.createdAt, "yyyy. MM. dd"); - +const ArticleItem: React.FC = ({ article }) => { return ( <> - + {article.title} {article.image && ( @@ -51,13 +49,11 @@ const ArticleItem = ({ article }: ArticleItemProps) => { )} - - - {article.writer.nickname} {dateString} - + + - + @@ -65,11 +61,15 @@ const ArticleItem = ({ article }: ArticleItemProps) => { ); }; -type AllArticlesSectionProps = { +const AddArticleLink = styled(StyledLink)``; + +interface AllArticlesSectionProps { initialArticles: Article[]; } -const AllArticlesSection = ({initialArticles}: AllArticlesSectionProps) => { +const AllArticlesSection: React.FC = ({ + initialArticles, +}) => { const [orderBy, setOrderBy] = useState("recent"); const [articles, setArticles] = useState(initialArticles); diff --git a/components/board/ArticleCommentSection.tsx b/components/board/ArticleCommentSection.tsx new file mode 100644 index 00000000..8a4d9fd9 --- /dev/null +++ b/components/board/ArticleCommentSection.tsx @@ -0,0 +1,49 @@ +import { ChangeEvent, useState } from "react"; +import { TextArea } from "@/styles/CommonStyles"; +import ArticlePageCommentThread from "@/components/board/ArticlePageCommentThread"; +import { + CommentInputSection, + CommentSectionTitle, + PostCommentButton, +} from "@/styles/CommentStyles"; + +interface ArticleCommentSectionProps { + articleId: number; +} + +const ArticleCommentSection: React.FC = ({ + articleId, +}) => { + const [comment, setComment] = useState(""); + + const handleInputChange = (e: ChangeEvent) => { + setComment(e.target.value); + }; + + const handlePostComment = () => {}; + + return ( + <> + + 댓글 달기 + +