Skip to content

Commit 866c8ba

Browse files
authored
Feat/write#19 (#127)
* [feat] 글쓰기 기능 * [feat] 포스트 작성 기능 * Feat/communityscroll#23 (#114) * [feat] 스크롤링구현 * [feat] 주소, api설정 * [feat] 커뮤니티 탭, 필터 패치로직 * [feat] lastLikeCount, lastCommentCount, 추가 * [fix] 코멘트 삭제수정 마이페이지에선 뗄수있게 myPage props 추가 * 옵셔널로 수정 * 오류 수정 * [feat] 글쓰기 기능 * 카테고리필수 * [feat] 포스트 무한스크롤 + 글쓰기기능 이미지추가 * [feat] 이미지 스와이퍼 * [feat] 프로필 쑤리 이미지 * [feat] 댓글 누르면 댓글 섹션으로 가기 * [feat] 좋아요기능(아직 좋아요받아오는건 못함 api필요) * [feat] 게시물 수정 * [feat] 글 수정 * [refactor] 코드 조금정리 * [feat] 작성자본인만 글수정삭제 * [feat]글 삭제기능 * [feat] 칵테일태그 * [fix]칵테일, 쉐어 기능 * 수 라우터, 비로그인처리 * 타입 수정 * 타입 수정 * 타입수정 * 타입수정 * 타입수정 * 오류수정 * 오류수정 * 오류수정 * 오류수정 * 오류수정 * 충돌해결 * 오류 수정 * 오류 수정 * 오류 수정 * [fix] 이미지 카운트, 10개 제한 * [fix] 글쓰기 placeholder * [fix] 공유 url 수정 * [fix] 프로필배경 지우기 * [fix] 플로팅탭 미디어쿼리 수정 * [fix] 수정 모달 * 댓글실시간반영 시도 * 수정 * [fix] 수정모달 로직 수정 * 수정로직 수정
1 parent ba76040 commit 866c8ba

File tree

17 files changed

+155
-79
lines changed

17 files changed

+155
-79
lines changed

src/app/community/edit/[postId]/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { useParams } from 'next/navigation';
66

77
function Page() {
88
const params = useParams();
9+
console.log(params);
910

1011
return (
1112
<div className="w-full mb-20 flex relative">

src/domains/community/detail/DetailContent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function DetailContent({
3939
<CocktailTag use="detail" selectedTags={tags} />
4040
<PostInfo createdAt={createdAt} viewCount={viewCount} commentCount={commentCount} />
4141

42-
<div className="block md:hidden mt-2">
42+
<div className="block lg:hidden mt-2">
4343
<DetailTabMobile
4444
likeCount={prevLikeCount ?? 0}
4545
like={like}

src/domains/community/detail/DetailPage.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ import { useParams } from 'next/navigation';
1414
import { useAuthStore } from '@/domains/shared/store/auth';
1515
import Button from '@/shared/components/button/Button';
1616
import { useRouter } from 'next/navigation';
17+
import { useComments } from '../hook/useComment';
1718

1819
function DetailPage() {
1920
const params = useParams();
2021
const postId = params.id;
2122

23+
const user = useAuthStore((state) => state.user);
24+
2225
const [postDetail, setPostDetail] = useState<Post | null>(null);
2326
const [isLoading, setIsLoading] = useState(false);
2427
const [like, setLike] = useState(false);
@@ -27,6 +30,8 @@ function DetailPage() {
2730
const isLoggedIn = useAuthStore((state) => state.isLoggedIn);
2831
const router = useRouter();
2932

33+
const { comments } = useComments(postId, user);
34+
3035
const commentRef = useRef<HTMLElement | null>(null);
3136

3237
useEffect(() => {
@@ -119,7 +124,7 @@ function DetailPage() {
119124
</section>
120125
</article>
121126
{isLoggedIn && (
122-
<div className="hidden md:block">
127+
<div className="hidden lg:block">
123128
<DetailTabDesktop
124129
likeCount={prevLikeCount ?? 0}
125130
commentCount={commentCount}
@@ -128,6 +133,7 @@ function DetailPage() {
128133
onLikeToggle={handleLike}
129134
title={title}
130135
imageUrls={imageUrls}
136+
comments={comments}
131137
/>
132138
</div>
133139
)}

src/domains/community/detail/tab/DetailTabDesktop.tsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import CommentBtn from '../../components/comment/CommentBtn';
55
import LikeBtn from '../../components/like/LikeBtn';
66
import ShareModal from '@/domains/shared/components/share/ShareModal';
77
import { RefObject, useState } from 'react';
8+
import { useParams } from 'next/navigation';
9+
import { CommentType } from '../../types/post';
810

911
type Props = {
1012
likeCount: number;
@@ -14,6 +16,7 @@ type Props = {
1416
onLikeToggle: () => void;
1517
title: string;
1618
imageUrls: string[];
19+
comments: CommentType[] | null;
1720
};
1821

1922
interface Meta {
@@ -30,10 +33,14 @@ function DetailTabDesktop({
3033
onLikeToggle,
3134
title,
3235
imageUrls,
36+
comments,
3337
}: Props) {
3438
const [isShare, setIsShare] = useState(false);
3539
const [meta, setMeta] = useState<Meta | null>(null);
3640

41+
const params = useParams();
42+
const postId = params?.id;
43+
3744
const handleClick = () => {
3845
if (commentRef.current) {
3946
const top = commentRef.current.getBoundingClientRect().top + window.scrollY - 100; // 100px 위로 offset
@@ -43,15 +50,13 @@ function DetailTabDesktop({
4350

4451
// ✅ 공유 버튼 클릭 시 meta 생성
4552
const handleShareClick = () => {
46-
if (typeof window !== 'undefined') {
47-
const currentUrl = window.location.href;
48-
setMeta({
49-
title,
50-
url: currentUrl,
51-
imageUrl: imageUrls[0] || getOgImage(),
52-
});
53-
setIsShare(true);
54-
}
53+
const currentUrl = `http://www.ssoul.life/community/${postId}`;
54+
setMeta({
55+
title,
56+
url: currentUrl,
57+
imageUrl: imageUrls[0] || getOgImage(),
58+
});
59+
setIsShare(true);
5560
};
5661

5762
// ✅ og:image 메타태그에서 이미지 가져오기 (fallback용)
@@ -64,7 +69,7 @@ function DetailTabDesktop({
6469
<>
6570
<section
6671
aria-label="게시글 인터랙션 버튼"
67-
className="absolute top-[50px] 2xl:right-80 xl:right-50 lg:right-10 md:right-10 z-10 h-full transition-transform duration-300 ease-in-out"
72+
className="absolute top-[50px] 2xl:right-60 xl:right-50 lg:right-10 md:right-10 z-10 h-full transition-transform duration-300 ease-in-out"
6873
>
6974
<div className="sticky top-[183px]">
7075
<div className="flex md:flex-col md:gap-10 w-full h-full">
@@ -74,7 +79,7 @@ function DetailTabDesktop({
7479
</div>
7580
<div className="flex md:flex-col justify-center items-center gap-2 text-sm text-gray">
7681
<CommentBtn size="md" onClick={handleClick} />
77-
<span>{commentCount}</span>
82+
<span>{comments?.length}</span>
7883
</div>
7984
<div>
8085
<Share variants="community" size="md" onClick={handleShareClick} />

src/domains/community/detail/tab/DetailTabMobile.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Share from '@/domains/shared/components/share/Share';
44
import LikeBtn from '../../components/like/LikeBtn';
55
import { useState } from 'react';
66
import ShareModal from '@/domains/shared/components/share/ShareModal';
7+
import { useParams } from 'next/navigation';
78

89
type Props = {
910
likeCount: number;
@@ -23,16 +24,17 @@ function DetailTabMobile({ likeCount, onLikeToggle, like, title, imageUrls }: Pr
2324
const [isShare, setIsShare] = useState(false);
2425
const [meta, setMeta] = useState<Meta | null>(null);
2526

27+
const params = useParams();
28+
const postId = params?.id;
29+
2630
const handleShareClick = () => {
27-
if (typeof window !== 'undefined') {
28-
const currentUrl = window.location.href;
29-
setMeta({
30-
title,
31-
url: currentUrl,
32-
imageUrl: imageUrls[0] || getOgImage(),
33-
});
34-
setIsShare(true);
35-
}
31+
const currentUrl = `http://www.ssoul.life/community/${postId}`;
32+
setMeta({
33+
title,
34+
url: currentUrl,
35+
imageUrl: imageUrls[0] || getOgImage(),
36+
});
37+
setIsShare(true);
3638
};
3739

3840
// ✅ og:image 메타태그에서 이미지 가져오기 (fallback용)

src/domains/community/hook/useComment.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { CommentType } from '../types/post';
55
import { User } from '@/domains/shared/store/auth';
66
import { ParamValue } from 'next/dist/server/request/params';
77

8-
export function useComments(postId: ParamValue, user: User | null, accessToken: string | null) {
8+
export function useComments(postId: ParamValue, user: User | null, accessToken?: string | null) {
99
const [comments, setComments] = useState<CommentType[] | null>(null);
1010
const [isEnd, setIsEnd] = useState(false);
1111
const [isLoading, setIsLoading] = useState(false);
@@ -23,7 +23,7 @@ export function useComments(postId: ParamValue, user: User | null, accessToken:
2323

2424
useEffect(() => {
2525
fetchData();
26-
}, [fetchData]);
26+
}, [postId]);
2727

2828
const handleUpdateComment = async (commentId: number, content: string) => {
2929
if (!user) {
@@ -39,6 +39,8 @@ export function useComments(postId: ParamValue, user: User | null, accessToken:
3939
)
4040
: prev
4141
);
42+
const updatedComments = await fetchComment(postId);
43+
setComments(updatedComments);
4244
} catch (err) {
4345
console.error(err);
4446
alert('댓글 수정 중 오류가 발생했습니다.');
@@ -61,6 +63,8 @@ export function useComments(postId: ParamValue, user: User | null, accessToken:
6163
setComments((prev) =>
6264
prev ? prev.filter((c) => c.commentId !== deleteTarget.commentId) : prev
6365
);
66+
const updatedComments = await fetchComment(postId);
67+
setComments(updatedComments);
6468
} catch (err) {
6569
console.error(err);
6670
alert('댓글 삭제 중 오류가 발생했습니다.');

src/domains/community/main/CommunityFilter.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ function CommunityFilter({ posts, setPosts }: Props) {
2222
const query = searchParams.get('category');
2323
const router = useRouter();
2424

25-
useEffect(() => {
26-
console.log(query);
27-
}, [query]);
28-
2925
const handleChange = async (selectTitle: string) => {
3026
if (!query) return;
3127

src/domains/community/main/PostCard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function PostCard({ posts, isLoading, isEnd, onLoadMore }: Props) {
6161
return (
6262
<article
6363
className="py-4 sm:py-5 border-b-1 border-gray-light"
64-
key={postId}
64+
key={postId + createdAt}
6565
ref={(el) => {
6666
if (index === 0) firstItemRef.current = el;
6767
if (isLast) {

src/domains/community/write/CompleteBtn.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
import Button from '@/shared/components/button/Button';
22

3-
function CompleteBtn({ mode }: { mode: 'edit' | 'create' }) {
3+
type Props = {
4+
mode: 'edit' | 'create';
5+
setEditDone: (value: boolean) => void;
6+
handleEditLogic: () => Promise<boolean>;
7+
};
8+
9+
function CompleteBtn({ mode, setEditDone, handleEditLogic }: Props) {
410
return (
511
<div className="w-full flex items-center justify-end mt-10">
6-
<Button type="submit" size="default" color="default">
12+
<Button
13+
type={mode === 'create' ? 'submit' : 'button'}
14+
size="default"
15+
color="default"
16+
onClick={async () => {
17+
setEditDone(true);
18+
}}
19+
>
720
{mode === 'create' ? '올리기' : '수정하기'}
821
</Button>
922
</div>

src/domains/community/write/WriteForm.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ function WriteForm({ formData, setFormData }: Props) {
1616
</label>
1717
<textarea
1818
id="content"
19+
placeholder="내용을 입력해주세요."
1920
role="textbox"
2021
aria-multiline="true"
2122
tabIndex={0}

0 commit comments

Comments
 (0)