diff --git a/src/pages/CommunityPage/CommunityList.jsx b/src/pages/CommunityPage/CommunityList.jsx index 4bc89c0..33b5adb 100644 --- a/src/pages/CommunityPage/CommunityList.jsx +++ b/src/pages/CommunityPage/CommunityList.jsx @@ -1,130 +1,155 @@ -import axios from '../../apis/AxiosInstance'; -import { useEffect, useState } from 'react'; -import { FcLike } from 'react-icons/fc'; -import { IoChatbubbleEllipsesOutline } from 'react-icons/io5'; -import { useNavigate } from 'react-router-dom'; -import styled from 'styled-components'; -import { images } from '../../components/Images'; +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import styled from "styled-components"; +import { FcLike } from "react-icons/fc"; +import { IoChatbubbleEllipsesOutline } from "react-icons/io5"; +import axios from "../../apis/AxiosInstance"; +import { HiArrowSmDown } from "react-icons/hi"; +import { LuSearch } from "react-icons/lu"; const CommunityList = () => { const navigate = useNavigate(); - const [comunityList, setComunityList] = useState([]); + const [communityList, setCommunityList] = useState([]); const [comments, setComments] = useState([]); - const [activeCategory, setActiveCategory] = useState('전체'); - const category = [ - { src: images.categoryAll, name: '전체' }, - { src: images.categoryFreedom, name: '자유' }, - { src: images.categoryDongNea, name: '동네' }, - { src: images.categoryExpert, name: '전문가' }, - { src: images.categoryAnonymity, name: '익명' }, - { src: images.categoryEvent, name: '이벤트' }, - ]; + const [latest, setLatest] = useState(false); + const [userNicknames, setUserNicknames] = useState({}); + // 게시글 목록 불러오기 useEffect(() => { axios - .get('https://ureca.store/api/communities') - .then(response => { - setComunityList(response.data); // 응답 데이터 저장 - console.log('게시글 목록:', response.data); + .get("/communities") + .then((response) => { + setCommunityList(response.data); + console.log("게시글 목록:", response.data); + response.data.forEach((item) => { + if (!userNicknames[item.user]) { + fetchUserNickname(item.user); + } + }); }) - .catch(error => { - console.error('Error fetching data:', error); + .catch((error) => { + console.error("Error fetching data:", error); }); }, []); + // 사용자 닉네임 가져오기 함수 + const fetchUserNickname = (userId) => { + axios + .get(`/user/${userId}`) + .then((response) => { + setUserNicknames((prev) => ({ + ...prev, + [userId]: response.data.nickname, + })); + }) + .catch((error) => { + console.error("Error fetching user nickname:", error); + }); + }; + // 좋아요 수 증가 함수 - const good = postId => { - const updatedItemList = comunityList.map(item => { + const good = (postId) => { + const updatedItemList = communityList.map((item) => { if (item.postId === postId) { const updatedGood = (item.good || 0) + 1; - // 서버의 좋아요 수 업데이트 요청 axios - .put(`https://ureca.store/api/communities/${postId}`, { ...item, good: updatedGood }) - .then(response => { - console.log('좋아요 업데이트:', response.data); + .put(`/communities/${postId}`, { + ...item, + good: updatedGood, + }) + .then((response) => { + console.log("좋아요 업데이트:", response.data); }) - .catch(error => { - console.error('좋아요 업데이트 실패:', error); + .catch((error) => { + console.error("좋아요 업데이트 실패:", error); }); return { ...item, good: updatedGood }; } return item; }); - setComunityList(updatedItemList); + setCommunityList(updatedItemList); }; // 댓글 목록 불러오기 useEffect(() => { axios - .get(`https://ureca.store/api/communityComments`) - .then(response => { + .get(`/communityComments`) + .then((response) => { setComments(response.data); - console.log('댓글 목록 :', response.data); + console.log("댓글 목록 :", response.data); }) - .catch(error => { - console.error('Error fetching data:', error); + .catch((error) => { + console.error("Error fetching data:", error); }); }, []); + // 최신순 정렬 함수 + const handleLatest = () => { + const sortedList = [...communityList].sort( + (a, b) => new Date(b.createdAt) - new Date(a.createdAt) + ); + setCommunityList(sortedList); + setLatest(true); + }; + return ( - - 고양이가 세상을 지배한다 - { - navigate('/community/write'); - }}> - 글 작성 - - - - {category.map((item, index) => ( - setActiveCategory(item.name)}> - - {item.name} - - ))} - + + + + + + 최신순 + + + { + navigate("/community/write"); + }} + > + 글 작성 + + + + + 전체 {communityList.length.toLocaleString()}개 - {comunityList - .slice() - .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)) - .map(item => ( -
- { - e.preventDefault(); - navigate(`/community/detail/${item.postId}`); - }}> - - - 제목 : {item.title} - - 작성자{item.user} - - {new Date(item.createdAt).toLocaleDateString('ko-KR', { - timeZone: 'Asia/Seoul', - })} - - { - e.stopPropagation(); - good(item.postId); - }} - /> - {item.good || 0} - - {comments.filter(comment => comment.post === item.postId).length} - - - - - -
-
- {' '} -
- ))} + {communityList.map((item) => ( + { + e.preventDefault(); + navigate(`/community/detail/${item.postId}`); + }} + > + + + {item.title} + + 작성자: {userNicknames[item.user] || "로딩 중..."} + + + {new Date(item.createdAt).toLocaleDateString("ko-KR", { + timeZone: "Asia/Seoul", + })} + + { + e.stopPropagation(); + good(item.postId); + }} + /> + {item.good || 0} + + { + comments.filter((comment) => comment.post === item.postId) + .length + } + + + + + ))}
); @@ -133,31 +158,59 @@ const CommunityList = () => { export default CommunityList; const ItemTitle = styled.div` - height: 100vh; + height: 100%; width: 100%; - padding: 64px 0px 64px 0px; + padding: 64px 25px 64px 25px; display: flex; flex-direction: column; `; -const Col = styled.div` - width: 100%; +const Buttons = styled.div` + position: absolute; + right: 0px; display: flex; - justify-content: space-between; + gap: 5px; +`; +const Box = styled.input` + width: 50%; + height: 30px; + margin: 10px 0px; + padding-left: 10px; + border-radius: 5px; + border: 1px solid #f0f0f0; + background-color: #f0f0f0; + outline: none; + &::placeholder { + font-size: 12px; + color: #b3b3b3; + } +`; +const HiArrowSmDown1 = styled(HiArrowSmDown)` + font-size: 20px; `; -const Div = styled.div` +const Search = styled.div` width: 100%; + position: relative; display: flex; align-items: center; - flex-direction: column; + justify-content: space-between; `; -const CommunityText = styled.div` +const LuSearch1 = styled(LuSearch)` + position: absolute; + top: 16px; + left: 43%; + border-radius: 15px; + color: #b3b3b3; +`; +const ButtonCh = styled.button` display: flex; align-items: center; - justify-content: center; - flex-direction: column; - margin-left: 15px; + border-radius: 8px; + padding: 3px 0px 3px 6px; + &:hover { + background-color: #f0f0f0; + } `; -const WriteBtn = styled.button` +const BuWrite = styled.button` width: 64px; height: 28px; font-size: 12px; @@ -166,61 +219,37 @@ const WriteBtn = styled.button` border-radius: 8px; border: 1px solid #ff6e00; outline: none; - transition: border-color 0.3s; align-items: center; justify-content: center; color: white; - margin-right: 15px; -`; -const Category = styled.div` - width: 100%; - height: 83px; - padding: 10px; - background-color: #f5f5f5; - display: flex; - justify-content: space-around; - margin: 10px 0px; - align-items: center; -`; -const CategoryBtn = styled.div` - display: flex; - font-size:13px ; - flex-direction: column; - align-items: center; cursor: pointer; - opacity: ${({ $active }) => ($active ? '1' : '0.5')}; - transition: opacity 0.3s; - &:hover { - opacity: 1; - } `; -const CategoryImg = styled.img` - width: 25px; - height: 30px; +const All = styled.div` + font-size: 12px; + color: #8d8d8d; + margin: 10px 0px; `; - const RowLi = styled.div` display: flex; - flex-wrap: wrap; // 화면에 맞춰 자동 줄바꿈 - margin: 0px; // Col 패딩 균등 조절 + flex-wrap: wrap; + gap: 16px; + margin: 0 -8px; `; const Lists = styled.div` width: 100%; display: flex; flex-direction: row; height: 50px; - margin: 0px 25px; `; const ListImg = styled.img` width: 50px; height: 50px; background-color: #d9d9d9; - margin-left: 20px; border-radius: 8px; - flex-shrink: 0; /* 이미지 크기를 고정 */ - background-image: url(${props => props.src}); /* 이미지 URL 설정 */ - background-size: cover; /* 이미지를 채우도록 설정 */ - background-position: center; /* 이미지 중앙 정렬 */ + flex-shrink: 0; + background-image: url(${(props) => props.src}); + background-size: cover; + background-position: center; cursor: pointer; `; const ListTitlesContainer = styled.div` @@ -228,39 +257,36 @@ const ListTitlesContainer = styled.div` width: 100%; flex-direction: column; align-items: center; - justify-content: space-between; /* 상하 간격 자동 배분 */ + justify-content: space-between; padding: 5px; + cursor: pointer; `; const ListTItle = styled.div` display: flex; - font-size: 14px; + font-size: 16px; font-weight: bold; width: 100%; align-self: center; `; const ListUser = styled.div` - font-size: 10px; + font-size: 12px; color: #8d8d8d; display: flex; - /* width: 90%; */ + width: 100%; align-self: center; - justify-content: flex-start; `; const ListDate = styled.div` - font-size: 10px; - color: #8d8d8d; display: flex; + font-size: 12px; + color: #8d8d8d; width: 100%; align-items: center; - justify-content: space-between; + justify-content: flex-end; `; -const DI = styled.div` +const Icons = styled.div` display: flex; align-items: center; - justify-content: space-between; - margin-right: 20px; -`; -const Icons = styled.div` + gap: 2px; font-size: 14px; color: #8d8d8d; margin-left: 5px; @@ -269,10 +295,6 @@ const FcLike1 = styled(FcLike)` font-size: 16px; cursor: pointer; `; -const Hr = styled.div` - width: 100%; - color: #8d8d8d; -`; const Comment1 = styled(IoChatbubbleEllipsesOutline)` font-size: 16px; margin-left: 10px;