Skip to content

Commit

Permalink
Merge pull request #134 from soohwanpak/next-박수환-sprint9
Browse files Browse the repository at this point in the history
[박수환] sprint9
  • Loading branch information
pers0n4 authored Jan 2, 2025
2 parents 2f5f746 + 9b39cb6 commit a01bfa3
Show file tree
Hide file tree
Showing 40 changed files with 1,203 additions and 138 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
!.yarn/plugins
!.yarn/releases
!.yarn/versions

/test.http
# testing
/coverage

Expand Down
18 changes: 15 additions & 3 deletions components/ArticleCommentDropDown.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useRef, useEffect } from 'react';
import styles from '@/css/Dropdown.module.css';
import Image from 'next/image';
import instance from '@/lib/axios';
import instance from '@/lib/instance';

export default function ArticleCommentDropDown({ id, onCommentAdded }) {
const [isOpen, setIsOpen] = useState(false);
Expand All @@ -15,9 +15,15 @@ export default function ArticleCommentDropDown({ id, onCommentAdded }) {
};

const handlePatch = () => {
const accessToken = localStorage.getItem('accessToken');

try {
instance.patch(`/articleComment/${id}`, {
instance.patch(`/comments/${id}`, {
content: editContent,
}, {
headers: {
Authorization: `Bearer ${accessToken}`,
}
});
alert('댓글이 수정되었습니다!');
setIsEditing(!isEditing);
Expand All @@ -29,7 +35,13 @@ export default function ArticleCommentDropDown({ id, onCommentAdded }) {
}

const handleDelete = () => {
instance.delete(`/articleComment/${id}`)
const accessToken = localStorage.getItem('accessToken');

instance.delete(`/comments/${id}`, {
headers: {
Authorization: `Bearer ${accessToken}`,
}
})
.then((response) => {
alert("댓글이 삭제되었습니다!");
onCommentAdded();
Expand Down
31 changes: 17 additions & 14 deletions components/ArticleDetail.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Image from 'next/image';
import dayjs from "dayjs";
import { useRouter } from 'next/router';
import { useState } from 'react';
import instance from '@/lib/axios';
import instance from '@/lib/instance';
import ArticleDropDown from './ArticleDropDown';
import ArticleCommentDropDown from './ArticleCommentDropDown';

Expand All @@ -20,9 +20,13 @@ export default function ArticleDetail({ article, onCommentAdded }) {
alert('내용을 입력해주세요!');
}
if (content) {
instance.post(`/articleComment`, {
articleId: article.id,
const accessToken = localStorage.getItem('accessToken');
instance.post(`/articles/${article.id}/comments`, {
content,
}, {
headers: {
Authorization: `Bearer ${accessToken}`,
}
}).then((response) => {
alert("댓글이 등록되었습니다!");
onCommentAdded();
Expand All @@ -45,7 +49,7 @@ export default function ArticleDetail({ article, onCommentAdded }) {
<div className={styles.ArticleDetailText}>
{article.title}
</div>
<ArticleDropDown id={article.id} />
<ArticleDropDown id={article.id} authorId={article.writer.id} />
</div>
<div className={styles.ArticleDetailMain}>
<div className={styles.ArticleDetailUser}>
Expand All @@ -55,7 +59,7 @@ export default function ArticleDetail({ article, onCommentAdded }) {
height={40}
src="/images/userIcon.png" alt="User" />
</div>
<div className={styles.ArticleDetailUserName}>{article.user}</div>
<div className={styles.ArticleDetailUserName}>{article.writer.nickname}</div>
<div className={styles.ArticleDetailDate}>{dayjs(article.createdAt).format('YYYY. MM. DD')}</div>
</div>
<div className={styles.ArticleDetailLikeContain}>
Expand All @@ -65,7 +69,7 @@ export default function ArticleDetail({ article, onCommentAdded }) {
height={36}
src="/images/heart.png" alt="heart" />
</div>
<div className={styles.ArticleDetailLikeCount}>{article.like}</div>
<div className={styles.ArticleDetailLikeCount}>{article.likeCount}</div>
</div>
</div>

Expand All @@ -86,9 +90,8 @@ export default function ArticleDetail({ article, onCommentAdded }) {
className={styles.ArticleDetailCommentReg}>등록</div>
</div>


{article.ArticleComment && article.ArticleComment.length > 0 ? (
article.ArticleComment.map((comment, index) => (
{article.comments && article.comments.length > 0 ? (
article.comments.map((comment, index) => (
<div key={index} className={styles.ArticleDetailCommentBoxContain}>
<div className={styles.ArticleDetailCommentBox}>
<div>
Expand All @@ -100,15 +103,15 @@ export default function ArticleDetail({ article, onCommentAdded }) {
<div className={styles.ArticleDetailCommentUserAll}>
<div>
<Image
width={40}
height={40}
width={32}
height={32}
src="/images/userIcon.png"
alt="User"
/>
</div>
<div className={styles.ArticleDetailCommentUser}>
<div className={styles.ArticleDetailCommentUserName}>
{comment.user}
{comment.writer ? comment.writer.nickname : "익명"}
</div>
<div className={styles.ArticleDetailCommentUserTime}>
{dayjs(comment.createdAt).format('YYYY. MM. DD')}
Expand All @@ -123,7 +126,7 @@ export default function ArticleDetail({ article, onCommentAdded }) {
width={1200}
height={208}
src="/images/noComment.png"
alt="User"
alt="No Comments"
/>
</div>
)}
Expand All @@ -134,7 +137,7 @@ export default function ArticleDetail({ article, onCommentAdded }) {
width={240}
height={48}
src="/images/return.png"
alt="User"
alt="Return"
/>
</div>
</div>
Expand Down
41 changes: 32 additions & 9 deletions components/ArticleDropDown.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
import { useState, useRef, useEffect } from 'react';
import styles from '@/css/Dropdown.module.css';
import Image from 'next/image';
import instance from '@/lib/axios';
import instance from '@/lib/instance';
import { useRouter } from 'next/router';

export default function ArticleDropDown({ id }) {
export default function ArticleDropDown({ id, authorId }) {
const [isOpen, setIsOpen] = useState(false);
const [currentUser, setCurrentUser] = useState(null);
const dropdownRef = useRef(null);
const router = useRouter();

useEffect(() => {
const accessToken = localStorage.getItem('accessToken');
if (accessToken) {
const user = JSON.parse(localStorage.getItem('user'));
setCurrentUser(user);
} else {
console.log('Access token or user data not found');
}
}, []);

const toggleDropdown1 = () => {
setIsOpen(!isOpen);
};

const handleDelete1 = () => {
instance.delete(`/article/${id}`)
.then((response) => {
alert("게시글이 삭제되었습니다!");
router.push(`/`);
}).catch((error) => {
console.error(error);
});
const accessToken = localStorage.getItem('accessToken');
if (currentUser && currentUser.id === authorId) {
instance.delete(`/articles/${id}`, {
headers: {
Authorization: `Bearer ${accessToken}`,
}
})
.then((response) => {
console.log(response.data);
alert("게시글이 삭제되었습니다!");
router.push(`/`);
})
.catch((error) => {
console.error(error);
alert("삭제 실패, 다시 시도해주세요.");
});
} else {
alert("게시글을 삭제할 권한이 없습니다.");
}
};

const handlePatch = () => {
Expand Down
6 changes: 3 additions & 3 deletions components/BestItem.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import BestItemList from './BestItemList';
import { useState, useEffect } from "react";
import styles from '@/css/BestItem.module.css'
import instance from "@/lib/axios";
import instance from "@/lib/instance";

export default function BestItem({ }) {

const [posts, setPosts] = useState([]);

useEffect(() => {
instance.get(`/article/articleList?pageSize=3&orderBy='like'`)
instance.get(`/articles?page=1&pageSize=3&orderBy=like`)
.then((response) => {
setPosts(response.data.Articles);
setPosts(response.data.list);
})
.catch((error) => console.error(error));
}, []);
Expand Down
22 changes: 14 additions & 8 deletions components/BestItemList.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,44 @@ export default function BestItemList({ post }) {
const router = useRouter();

const handleClick = () => {
router.push(`/${post.id}/article`);
router.push(`/articles/${post.id}`);
};

return (
<>
<div className={styles.BestItemListContain} onClick={handleClick}>
<div className={styles.BestItemList}>
<Image
width={102}
height={30}
src="/images/BestImage.png" alt="Best" />
src="/images/BestImage.png"
alt="Best"
/>
<div className={styles.BestItemListText1}>
<div className={styles.BestItemListText11}>{post.content}</div>
<div className={styles.BestItemListText11}>
{post.title}
</div>
<div className={styles.BestItemImageBox}>
<Image
width={48}
height={45}
src="/images/bestitemimage.png" alt="Best" />
src={'/images/bestitemimage.png'}
alt="Post Image"
/>
</div>
</div>
<div className={styles.BestItemListText2}>
<div className={styles.BestItemListText22}>
<div>{post.user}</div>
<div>{post.writer.nickname}</div>
<div></div>
<div>{post.like}</div>
<div>{post.likeCount}</div>
</div>
<div>
<div>{dayjs(post.createdAt).format('YYYY. MM. DD')}</div>
</div>
</div>
</div>

</div>
</>
);
}
}
55 changes: 48 additions & 7 deletions components/Header.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,69 @@
import { useState, useEffect } from 'react';
import Image from 'next/image';
import Link from 'next/link';
import { useRouter } from 'next/router';
import styles from '@/css/Header.module.css';

export default function Header() {
const [nickname, setNickname] = useState(null);

useEffect(() => {
const accessToken = localStorage.getItem('accessToken');
const user = localStorage.getItem('user');

// 'accessToken'과 'user'가 존재하면 로그인된 상태로 처리
if (accessToken && user) {
const parsedUser = JSON.parse(user);
setNickname(parsedUser.nickname); // 사용자 닉네임 상태 설정
} else {
setNickname(null);
}
}, []);

const handleLogout = () => {
localStorage.removeItem('accessToken'); // accessToken 삭제
localStorage.removeItem('user'); // 사용자 정보 삭제
setNickname(null); // 상태 초기화
window.location.reload(); // 페이지 새로고침
};

return (
<div className={styles.headerContain}>
<div className={styles.header1}>
<div className={styles.header2}>
<Link href="/" ><Image
width={153}
height={51}
src="/images/PandaLogo.png" alt="Panda Market Logo" /></Link>
<Link href="/">
<Image
width={153}
height={51}
src="/images/PandaLogo.png"
alt="Panda Market Logo"
/>
</Link>

<div className={styles.headerText}>
<p><Link href="/" className={styles.headerText1}>자유게시판</Link></p>
<p><Link href="#" className={styles.headerText2}>중고마켓</Link></p>
</div>

<Link href='#' className={styles.button}>로그인</Link>
{nickname ? (
<div className={styles.userContainer}>
<div className={styles.userArea}>
<Image
width={40}
height={40}
src="/images/userIcon.png"
alt="userIcon"
/>
<div className={styles.nickname}>{nickname}</div>
</div>
<div onClick={handleLogout} className={styles.logoutButton}>
로그아웃
</div>
</div>
) : (
<Link href='/login' className={styles.button}>로그인</Link>
)}
</div>
</div>
</div >
</div>
);
}
8 changes: 4 additions & 4 deletions components/PostList.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useEffect } from "react";
import PostListAll from "./PostListAll";
import instance from "@/lib/axios";
import instance from "@/lib/instance";
import styles from "@/css/PostList.module.css";
import SearchInput from "./SearchInput";
import Dropdown from "./DropDown";
Expand All @@ -12,15 +12,15 @@ export default function PostList() {
const [orderby, setOrderby] = useState("recent");

useEffect(() => {
instance.get(`/article/articleList?pageSize=${pageSize}&keyword=${keyword}&orderBy=${orderby}`)
instance.get(`/articles?&pageSize=${pageSize}&keyword=${keyword}&orderBy=${orderby}`)
.then((response) => {
setPosts(response.data.Articles);
setPosts(response.data.list);
})
.catch((error) => console.error(error));
}, [pageSize, keyword, orderby]);

const handleClick = () => {
setPageSize(pageSize + 6);
setPageSize((prevSize) => prevSize + 6);
};

return (
Expand Down
Loading

0 comments on commit a01bfa3

Please sign in to comment.