Skip to content

Commit

Permalink
Merge pull request #674 from tkddbs587/Next.js-이영훈-sprint10
Browse files Browse the repository at this point in the history
[이영훈] sprint11
  • Loading branch information
jyh0521 authored Jun 15, 2024
2 parents 66fe21b + 1ccc8da commit fce7726
Show file tree
Hide file tree
Showing 41 changed files with 2,538 additions and 93 deletions.
59 changes: 42 additions & 17 deletions api/api.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const BASE_URL = "https://panda-market-api.vercel.app";
const BASE_URL = process.env.NEXT_PUBLIC_API;
export const RECENT = "recent";

export default async function getArticlesData({
export async function getArticlesData({
page = 1,
pageSize = 10,
orderBy = RECENT,
Expand All @@ -22,16 +22,19 @@ export async function getArticle(id) {
}

export async function getArticleComments({ articleId, limit }) {
const res = await fetch(
`${BASE_URL}/articles/${articleId}/comments?limit=${limit}`
);
const data = await res.json();

return data;
try {
const res = await fetch(
`${BASE_URL}/articles/${articleId}/comments?limit=${limit}`,
);
const data = await res.json();
return data;
} catch (error) {
console.log(error);
}
}

export async function postArticle(values) {
const accessToken = await getAccessToken();
const accessToken = localStorage.getItem("accessToken");

const res = await fetch(`${BASE_URL}/articles`, {
method: "POST",
Expand All @@ -45,13 +48,11 @@ export async function postArticle(values) {
}

export async function postFile(file) {
const accessToken = await getAccessToken();
const accessToken = localStorage.getItem("accessToken");

const res = await fetch(`${BASE_URL}/images/upload`, {
method: "POST",
headers: {
// "Content-Type": "multipart/form-data",
// 헤더에 "multipart/form-data"를 담아서 post 요청하니까 오류가남..
Authorization: `Bearer ${accessToken}`,
},
body: file,
Expand All @@ -60,7 +61,7 @@ export async function postFile(file) {
}

export async function postArticleComment({ articleId, content }) {
const accessToken = await getAccessToken();
const accessToken = localStorage.getItem("accessToken");
const res = await fetch(`${BASE_URL}/articles/${articleId}/comments`, {
method: "POST",
headers: {
Expand All @@ -72,18 +73,42 @@ export async function postArticleComment({ articleId, content }) {
return res;
}

export async function getAccessToken() {
export async function signUpUser(formValues) {
const res = await fetch(`${BASE_URL}/auth/signUp`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formValues),
});
const data = await res.json();
return data.user?.id;
}

export async function signInUser({ email, password }) {
const res = await fetch(`${BASE_URL}/auth/signIn`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: "hatesummer@email.com",
password: "password",
email,
password,
}),
});
const data = await res.json();
const accessToken = data.accessToken;
return accessToken;
localStorage.setItem("accessToken", accessToken);
return data.user?.id;
}

export async function deleteComment(commentId) {
const accessToken = localStorage.getItem("accessToken");

const res = await fetch(`${BASE_URL}/comments/${commentId}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
}
9 changes: 3 additions & 6 deletions components/ArticleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Image from "next/image";
import styles from "./ArticleCard.module.css";
import Link from "next/link";
import { Article } from "@/types";
import getFormattedDate from "@/utils/formatDate";

const ArticleCard = ({ item }: { item: Article }) => {
const {
Expand All @@ -12,15 +13,13 @@ const ArticleCard = ({ item }: { item: Article }) => {
image,
writer: { nickname },
} = item;
const date = new Date(createdAt);
const formattedDate = date.toISOString().split("T")[0];

return (
<Link href={`/addboard/${id}`}>
<div className={styles.ArticleCard}>
<div className={styles.section_top}>
<div className={styles.title}>{title}</div>
{image ? (
{image && (
<div className={styles.image}>
<Image
src={image}
Expand All @@ -29,15 +28,13 @@ const ArticleCard = ({ item }: { item: Article }) => {
alt="베스트게시글이미지"
/>
</div>
) : (
""
)}
</div>
<div className={styles.section_bottom}>
<div className={styles.section_left}>
<Image src="../images/logo.svg" alt="" width={24} height={24} />
<div className={styles.profile_name}>{nickname}</div>
<div className={styles.date}>{formattedDate}</div>
<div className={styles.date}>{getFormattedDate(createdAt)}</div>
</div>
<div className={styles.section_right}>
<Image
Expand Down
31 changes: 31 additions & 0 deletions components/ArticleComments.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,37 @@
color: var(--color-gray800);
}

.kebabButton {
display: flex;
position: relative;
}

.kebab {
cursor: pointer;
}

.kebabMenu {
padding: 8px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
width: 72px;
font-size: 14px;
border: 2px solid var(--color-gray200);
border-radius: 8px;
position: absolute;
left: 30px;
}

.fixButton {
cursor: pointer;
}

.deleteButton {
cursor: pointer;
}

.section_bottom {
padding-bottom: 24px;
display: flex;
Expand Down
52 changes: 41 additions & 11 deletions components/ArticleComments.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,59 @@
import { Comment } from "@/types";
import styles from "./ArticleComments.module.css";
import Image from "next/image";
import getFormattedDate from "@/utils/formatDate";
import { Dispatch, MouseEvent, SetStateAction, useState } from "react";

const ArticleComments = ({ comment }: { comment: Comment }) => {
const { content, createdAt } = comment;
const ArticleComments = ({
comment,
handleDeleteComment,
}: {
comment: Comment;
handleDeleteComment: (id: number) => void;
}) => {
const [kebabButton, setKebabButton] = useState(false);

const { id, content, createdAt } = comment;
const { nickname } = comment.writer;
const date = new Date(createdAt);
const formattedDate = date.toISOString().split("T")[0];

const handleMenuChange = (e: MouseEvent<HTMLImageElement>) => {
setKebabButton(!kebabButton);
};

const handleDeleteButton = () => {
handleDeleteComment(id);
};

return (
<div className={styles.ArticleComments}>
<div className={styles.section_top}>
<div className={styles.content}>{content}</div>
<Image
src="/images/ic_kebab.svg"
width={24}
height={24}
alt="케밥아이콘"
/>
<div className={styles.kebabButton}>
<Image
className={styles.kebab}
src="/images/ic_kebab.svg"
width={24}
height={24}
alt="케밥아이콘"
onClick={handleMenuChange}
/>
{kebabButton ? (
<div className={styles.kebabMenu}>
<div className={styles.fixButton}>수정하기</div>
<div className={styles.deleteButton} onClick={handleDeleteButton}>
삭제하기
</div>
</div>
) : (
""
)}
</div>
</div>
<div className={styles.section_bottom}>
<Image src="/images/logo.svg" width={32} height={32} alt="유저이미지" />
<div className={styles.section_bottom_right}>
<div className={styles.nickname}>{nickname}</div>
<div className={styles.date}>{formattedDate}</div>
<div className={styles.date}>{getFormattedDate(createdAt)}</div>
</div>
</div>
</div>
Expand Down
5 changes: 2 additions & 3 deletions components/ArticleFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import Image from "next/image";
import styles from "./ArticleFeed.module.css";
import { Article } from "@/types";
import getFormattedDate from "@/utils/formatDate";

const ArticleFeed = ({ article }: { article: Article }) => {
const { title, createdAt, likeCount, content } = article;
const { nickname } = article.writer;
const date = new Date(createdAt);
const formattedDate = date.toISOString().split("T")[0];

return (
<div className={styles.ArticleFeed}>
Expand All @@ -28,7 +27,7 @@ const ArticleFeed = ({ article }: { article: Article }) => {
alt="프로필이미지"
/>
<div className={styles.nickname}>{nickname}</div>
<div className={styles.date}>{formattedDate}</div>
<div className={styles.date}>{getFormattedDate(createdAt)}</div>
</div>
<div className={styles.section_middle_right}>
<Image
Expand Down
26 changes: 21 additions & 5 deletions components/ArticleFeedComments.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ChangeEvent, SyntheticEvent, useEffect, useState } from "react";
import styles from "./ArticleFeedComments.module.css";
import { getArticleComments } from "../api/api";
import { postArticleComment } from "../api/api";
import { deleteComment, getArticleComments } from "@/api/api";
import { postArticleComment } from "@/api/api";
import ArticleComments from "./ArticleComments";
import { Comment } from "@/types";

Expand All @@ -10,14 +10,26 @@ const ArticleFeedComments = ({ id }: { id: string }) => {
const [comments, setComments] = useState<Comment[]>([]);
const [isChangeComments, setIsChangeComments] = useState<boolean>(false);

const isButtonDisabled = content.trim() === "" ? true : false;

const handleInputChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
setContent(e.target.value);
};
const isButtonDisabled = content.trim() === "" ? true : false;

const handleDeleteComment = async (targetId: number) => {
const res = await deleteComment(targetId);

setComments((prevComments) =>
prevComments.filter((comment) => comment.id !== targetId),
);
};

useEffect(() => {
async function loadArticleComments(articleId: string) {
const data = await getArticleComments({ articleId: articleId, limit: 5 });
const data = await getArticleComments({
articleId: articleId,
limit: 5,
});
setComments(data.list);
}
loadArticleComments(id);
Expand Down Expand Up @@ -60,7 +72,11 @@ const ArticleFeedComments = ({ id }: { id: string }) => {
<div className={styles.comments}>
{comments.length
? comments.map((comment) => (
<ArticleComments comment={comment} key={comment.id} />
<ArticleComments
comment={comment}
key={comment.id}
handleDeleteComment={handleDeleteComment}
/>
))
: ""}
</div>
Expand Down
4 changes: 3 additions & 1 deletion components/Articles.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { useEffect, useState } from "react";
import ArticleCard from "./ArticleCard";
import ArticlesHeader from "./ArticlesHeader";
import getArticlesData from "../api/api";
import styles from "./Articles.module.css";
import { Article } from "@/types";
import { getArticlesData } from "@/api/api";

const Articles = () => {
const [articles, setArticles] = useState<Article[]>([]);
const [search, setSearch] = useState<string>("");
const [order, setOrder] = useState<string>("recent");

console.log(articles);

useEffect(() => {
async function loadData() {
const data = await getArticlesData({
Expand Down
6 changes: 3 additions & 3 deletions components/BestArticleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import Image from "next/image";
import styles from "./BestArticleCard.module.css";
import Link from "next/link";
import { Article } from "@/types";
import getFormattedDate from "@/utils/formatDate";
import React from "react";

const BestArticleCard = ({ article }: { article: Article }) => {
const { id, title, likeCount, createdAt, image } = article;
const { nickname } = article.writer;
const date = new Date(createdAt);
const formattedDate = date.toISOString().split("T")[0];

return (
<Link href={`/addboard/${id}`}>
Expand Down Expand Up @@ -50,7 +50,7 @@ const BestArticleCard = ({ article }: { article: Article }) => {
<div className={styles.like_count}>{likeCount}</div>
</div>
</div>
<div className={styles.date}>{formattedDate}</div>
<div className={styles.date}>{getFormattedDate(createdAt)}</div>
</div>
</div>
</Link>
Expand Down
6 changes: 4 additions & 2 deletions components/BestArticles.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useEffect, useState } from "react";
import getArticlesData from "../api/api";
import { Article } from "../types";
import BestArticleCard from "./BestArticleCard";
import styles from "./BestArticles.module.css";
import useScreenWidth from "../hooks/useScreenWidth";
import { Article } from "@/types";

import React from "react";
import { getArticlesData } from "../api/api";

const BestArticles = () => {
const [articles, setArticles] = useState<Article[]>([]);
Expand Down
2 changes: 1 addition & 1 deletion components/Dropdown.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
border: 1px solid #e5e7eb;
font-size: 16px;
font-weight: 400;
color: #1f2937;
color: var(--color-gray800);
}

@media (min-width: 768px) and (max-width: 1200px) {
Expand Down
Loading

0 comments on commit fce7726

Please sign in to comment.