Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/common/apis/blog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import {FolderRequest} from "../types/blog.tsx";
import {FolderRequest, PostListMemberRequest} from "../types/blog.tsx";
import axiosApi from "./AxiosApi.tsx";
import {postListMemberRequestToParameter} from "../util/url.tsx";

export const getMemberPosts = (postListMemberRequest: PostListMemberRequest) =>
axiosApi.get(`/post/member${postListMemberRequestToParameter(postListMemberRequest)}`);

export const saveAndUpdateFolder = (folderRequestList: FolderRequest[]) =>
axiosApi.put("/folders", folderRequestList);
7 changes: 7 additions & 0 deletions src/common/types/blog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,10 @@ export const toFolderRequestList = (folderTypeList: FolderType[]) => {

return result;
}

export interface PostListMemberRequest {
username: string,
folderId: string | null,
page: number,
size: number,
}
11 changes: 11 additions & 0 deletions src/common/util/url.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {PostListRequest} from "../types/post.tsx";
import {CommentListRequest} from "../types/comment.tsx";
import {PostListMemberRequest} from "../types/blog.tsx";

export const postListRequestToParameter = (postListRequest: PostListRequest) => {
const sorts = postListRequest.sorts.map(sort => `sorts=${sort}`).join("&");
Expand All @@ -16,3 +17,13 @@ export const commentListRequestToParameter = (commentListRequest: CommentListReq

return query;
}

export const postListMemberRequestToParameter = (postListMemberRequest: PostListMemberRequest) => {
let query =`?username=${postListMemberRequest.username}&page=${postListMemberRequest.page}&size=${postListMemberRequest.size}`;

if (postListMemberRequest.folderId) {
query += `&folderId=${postListMemberRequest.folderId}`;
}

return query;
}
4 changes: 2 additions & 2 deletions src/components/blog/BlogSideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {faker} from "@faker-js/faker/locale/ko";
import {OutlineLink} from "../common/OutlineButton.tsx";
import BlogTagCard from "./BlogTagCard.tsx";
import {getFolderTitle} from "../../common/util/string.tsx";
import ProfileImageCircle from "../common/ProfileImageCircle.tsx";

function BlogSideBar({folders, username, addTag, setSelectedFolder, bgColor, side}: {
folders: FolderType[],
Expand All @@ -20,8 +21,7 @@ function BlogSideBar({folders, username, addTag, setSelectedFolder, bgColor, sid
return (
<div className={`${bgColor} ${side && "h-screen overflow-y-scroll"}`}>
<div className="flex flex-col justify-start items-center py-4 gap-4 z-200">
<img className="border border-gray-300 size-32 rounded-full"
src={faker.image.avatar()} alt="username"/>
<ProfileImageCircle profileUrl={loginState.profileUrl} size="lg"/>
<div className="flex justify-center items-center text-2xl font-black">
{username}
</div>
Expand Down
10 changes: 3 additions & 7 deletions src/components/common/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import {useDispatch, useSelector} from "react-redux";
import {RootState} from "../../store.tsx";
import {useEffect, useRef, useState} from "react";
import {TextLink} from "./TextButton.tsx";
import {MdOutlinePerson, MdOutlineSearch} from "react-icons/md";
import {MdOutlineSearch} from "react-icons/md";
import IconButton from "./IconButton.tsx";
import {getProfile, logoutApi} from "../../common/apis/member.tsx";
import {login, logout} from "../../common/slices/loginSlice.tsx";
import ProfileImageCircle from "./ProfileImageCircle.tsx";

function Header() {

Expand Down Expand Up @@ -79,12 +80,7 @@ function Header() {
? <div ref={dashboardRef}>
<div
className="relative flex justify-around items-center w-full">
{loginState.profileUrl
? <img className="size-10 rounded-full border border-gray-200 hover:cursor-pointer"
onClick={handleDropDown}
src={loginState.profileUrl} alt="user_image"/>
: <MdOutlinePerson className="size-6 m-1 rounded-full hover:cursor-pointer"
onClick={handleDropDown}/>}
<ProfileImageCircle profileUrl={loginState.profileUrl} onClick={handleDropDown}/>
<div
className={`${isOpen ? "" : "hidden"} absolute z-50 top-12 right-0 bg-white divide-y divide-gray-100 rounded-lg shadow-sm w-44`}>
<div className="flex flex-col gap-1 px-4 py-3 text-sm text-gray-900">
Expand Down
31 changes: 31 additions & 0 deletions src/components/common/ProfileImageCircle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {MdOutlinePerson} from "react-icons/md";

function ProfileImageCircle({profileUrl, size, onClick, addStyle}: {
profileUrl: string,
size?: string,
onClick?: () => void,
addStyle?: string,
}) {

let imageSize = "size-";
let iconSize = "size-";
if (size === "lg") {
imageSize += "32";
iconSize += "28";
} else {
imageSize += "10";
iconSize += "6";
}


if (profileUrl) {
return <img className={`${imageSize} ${addStyle} rounded-full border border-gray-200 hover:cursor-pointer`}
onClick={onClick}
src={profileUrl} alt="user_image"/>;
}

return <MdOutlinePerson className={`${iconSize} ${addStyle} mx-auto text-gray-700 m-1 rounded-full hover:cursor-pointer`}
onClick={onClick}/>;
}

export default ProfileImageCircle;
2 changes: 1 addition & 1 deletion src/components/post/PostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {dateToKorean} from "../../common/util/date.tsx";
import {Link} from "react-router-dom";
import {FaRegComment, FaRegHeart} from "react-icons/fa6";

function PostCard(post: PostResponse) {
function PostCard({post}: {post: PostResponse}) {

const safeContent = DOMPurify.sanitize(post.content);
const url = getImgSrc(safeContent);
Expand Down
7 changes: 1 addition & 6 deletions src/pages/MainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,7 @@ function MainPage() {
{posts.map((post) => (
<PostCard
key={post.id}
id={post.id}
title={post.title}
content={post.content}
username={post.username}
tags={post.tags}
createdAt={post.createdAt}/>
post={post}/>
))}
</div>
</div>
Expand Down
55 changes: 37 additions & 18 deletions src/pages/blog/BlogPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@ import {FolderType} from "../../common/types/blog.tsx";
import BlogSideBar from "../../components/blog/BlogSideBar.tsx";
import IconButton from "../../components/common/IconButton.tsx";
import {PageResponse} from "../../common/types/common.tsx";
import {getMemberPosts} from "../../common/apis/blog.tsx";
import {PostResponse} from "../../common/types/post.tsx";

function BlogPage() {

const navigate = useNavigate();
const {username} = useParams();

const [page, setPage] = useState(0);
const [pageInfo, setPageInfo] = useState<PageResponse>({number: 0, size: 5, totalElements: 53, totalPages: 11});
const [pageInfo, setPageInfo] = useState<PageResponse>({
number: 0,
size: 3,
totalElements: 0,
totalPages: 0
});
const [posts, setPosts] = useState<PostResponse[]>([]);
const folderData: FolderType[] = [
{
id: crypto.randomUUID(),
Expand Down Expand Up @@ -119,7 +128,6 @@ function BlogPage() {
};
}, []);

const navigate = useNavigate();
useEffect(() => {
navigate(`/blog/${username}?folder=${selectedFolder?.id || ""}`);
}, [selectedFolder]);
Expand All @@ -136,10 +144,28 @@ function BlogPage() {
};
}, [isOpen]);

useEffect(() => {
if (username === undefined) {
return;
}

getMemberPosts({
username: username,
folderId: null,
page: page,
size: pageInfo.size,
})
.then((res) => {
setPosts(res.data.content);
setPageInfo(res.data.page);
})
.catch(error => error.response.data.message);
}, [username, page]);

return (
<BasicLayout>
<div
className={`${(isOpen) ? "opacity-50 backdrop-blur-sm z-10 overflow-y-hidden" : "z-10"} flex flex-col`}>
className={`${(isOpen) ? "opacity-50 backdrop-blur-sm z-10 overflow-y-hidden" : "z-10"} w-full flex flex-col`}>
<div className="flex justify-between items-center text-2xl font-jalnan px-4 pb-4">
<div>{username}의 블로그</div>
<IconButton
Expand All @@ -149,22 +175,15 @@ function BlogPage() {
</div>
<div className="grid lg:grid-cols-3">
<div className="lg:col-span-2 flex flex-col gap-y-4 p-4 lg:border-r border-r-gray-200">
{[Array.from({length: 3}).map(() => (
{posts.map((post) => (
<PostCard
key={faker.number.int().toString()}
id={faker.number.int().toString()}
title={faker.lorem.sentence()}
content={`${faker.lorem.paragraphs()}<img src=${faker.image.url({
width: 320,
height: 320
})}/>`}
username={username || faker.animal.cat()}
tags={[{
id: crypto.randomUUID(),
name: faker.word.sample()
}, {id: crypto.randomUUID(), name: faker.word.sample()}]}
createdAt={new Date()}/>
))]}
key={post.id}
post={post}/>
))}
{posts.length === 0 &&
<div className="mt-8 text-center text-gray-600">
작성된 게시글이 없습니다.
</div>}
<PaginationButton
pageInfo={pageInfo} setPage={setPage}/>
</div>
Expand Down
16 changes: 7 additions & 9 deletions src/pages/post/PostPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@ import {getComments, saveComment, updateComment} from "../../common/apis/comment
import {CommentResponse, CommentType} from "../../common/types/comment.tsx";
import {useSelector} from "react-redux";
import {RootState} from "../../store.tsx";
import {PageResponse} from "../../common/types/common.tsx";

function PostPage() {

const {id} = useParams();
const navigate = useNavigate();
const loginState = useSelector((state: RootState) => state.loginSlice);

const pageSize = 10;

const [post, setPost] = useState<PostResponse>({
id: "",
title: "",
Expand All @@ -34,7 +33,7 @@ function PostPage() {
});
const [commentInput, setCommentInput] = useState("");
const [comments, setComments] = useState<CommentType[]>([]);
const [pageInfo, setPageInfo] = useState({number: 0, totalPages: 0});
const [pageInfo, setPageInfo] = useState<PageResponse>({number: 0, size: 10, totalPages: 0, totalElements: 0});
const [trigger, setTrigger] = useState(false);

const handleCommentInput = (e: ChangeEvent<HTMLTextAreaElement>) => {
Expand Down Expand Up @@ -116,7 +115,7 @@ function PostPage() {
postId: post.id,
parentCommentId: parentId,
page: page,
size: pageSize,
size: pageInfo.size,
})
.then((res) => {
setComments(prevComments =>
Expand Down Expand Up @@ -160,11 +159,11 @@ function PostPage() {
postId: post.id,
parentCommentId: null,
page: pageInfo.number,
size: pageSize,
size: pageInfo.size,
})
.then((res) => {
setComments(prev => [...prev, ...getCommentType(res.data.content)]);
setPageInfo({number: pageInfo.number, totalPages: res.data.page.totalPages});
setPageInfo(res.data.page);
})
.catch((error) => alert(error.response.data.message));
}, [trigger]);
Expand Down Expand Up @@ -219,8 +218,6 @@ function PostPage() {
<div className="w-4xl mx-auto p-8 break-words"
dangerouslySetInnerHTML={{__html: safeContent}}/>
<div className="w-full max-w-4xl mx-auto p-8 rounded-2xl flex flex-col gap-y-0 my-8">
<p>댓글</p>

{loginState.isLogin
? <CommentTextField
value={commentInput}
Expand All @@ -234,13 +231,14 @@ function PostPage() {
<FillLink text={"로그인"} to={"/login"} addStyle={"w-fit"}/>
</div>
}
<p>댓글 ({pageInfo.totalElements})</p>
{comments.map((comment, i) =>
<CommentCard
key={i}
comment={comment}
handleLoadMoreSubComment={handleLoadMoreSubComment}
handleCommentSubmit={handleCommentSubmit}
pageSize={pageSize}/>)}
pageSize={pageInfo.size}/>)}
{pageInfo.number + 1 < pageInfo.totalPages &&
<LoadMoreButton
onClick={handleLoadMoreComment}
Expand Down
34 changes: 17 additions & 17 deletions src/pages/post/SearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import BasicLayout from "../../layout/BasicLayout.tsx";
import {MdArrowDropDown, MdOutlineClear, MdOutlineSearch} from "react-icons/md";
import {Ref, useEffect, useRef, useState} from "react";
import * as React from "react";
import PostCard from "../../components/post/PostCard.tsx";
// import PostCard from "../../components/post/PostCard.tsx";
import {faker} from "@faker-js/faker/locale/ko";
import {Link, useSearchParams} from "react-router-dom";
import {LoadMoreButton} from "../../components/common/FillButton.tsx";
Expand Down Expand Up @@ -153,22 +153,22 @@ function SearchResults({selectedTab}: { selectedTab: string }) {
if (selectedTab === "게시글") {
return (
<div className="my-2">
{(Array.from({length: 5}).map(() => (
<PostCard
key={faker.number.int().toString()}
id={faker.number.int().toString()}
title={faker.lorem.sentence()}
content={`${faker.lorem.paragraphs()}<img src=${faker.image.url({
width: 320,
height: 320
})}/>`}
username={faker.animal.cat()}
tags={[{
id: faker.number.int().toString(),
name: faker.word.sample()
}, {id: faker.number.int().toString(), name: faker.word.sample()}]}
createdAt={new Date()}/>
)))}
{/*{(Array.from({length: 5}).map(() => (*/}
{/* <PostCard*/}
{/* key={faker.number.int().toString()}*/}
{/* id={faker.number.int().toString()}*/}
{/* title={faker.lorem.sentence()}*/}
{/* content={`${faker.lorem.paragraphs()}<img src=${faker.image.url({*/}
{/* width: 320,*/}
{/* height: 320*/}
{/* })}/>`}*/}
{/* username={faker.animal.cat()}*/}
{/* tags={[{*/}
{/* id: faker.number.int().toString(),*/}
{/* name: faker.word.sample()*/}
{/* }, {id: faker.number.int().toString(), name: faker.word.sample()}]}*/}
{/* createdAt={new Date()}/>*/}
{/*)))}*/}
<LoadMoreButton onClick={() => {
}} addStyle={"w-full"}/>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/post/WritePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function WritePage() {
.then(() => {
alert("작성되었습니다.");
setExitPage(true);
navigate(`/blog/${loginState.username}username`);
navigate(`/blog/${loginState.username}`);
})
.catch((error) => alert(error.response.data.message))
.finally(() => setLoading(false));
Expand All @@ -105,7 +105,7 @@ function WritePage() {
.then(() => {
alert("수정되었습니다.");
setExitPage(true);
navigate(`/blog/${loginState.username}username`);
navigate(`/blog/${loginState.username}`);
})
.catch((error) => alert(error.response.data.message))
.finally(() => setLoading(false));
Expand Down
Loading