Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#37: 게시글 상세 댓글, 좋아요, 스크랩 기능 구현 #53

Merged
merged 66 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
1276d01
refactor: API 변동 사항 대응 (댓글과 게시글 조회 분리)
semnil5202 Feb 15, 2024
e9caaa9
rename: ModifyDropdown 훅 네임 변경
semnil5202 Feb 15, 2024
3edc736
refactor: 게시글 상세 수정 및 삭제 드롭다운 컴포넌트 분리
semnil5202 Feb 16, 2024
ac66bb9
fix: key 오류 수정
semnil5202 Feb 16, 2024
5a991a0
refactor: 댓글, 스크랩, 좋아요 하단 바 컴포넌트 분리
semnil5202 Feb 17, 2024
f521f30
feat: 스크랩(북마크) post 요청 기능 추가
semnil5202 Feb 18, 2024
8c87958
refactor: ReactionBar idea id 넘기도록 변경
semnil5202 Feb 18, 2024
87537f0
feat: 스크랩 토글 기능 구현
semnil5202 Feb 20, 2024
58dc87b
feat: 게시글 좋아요 기능 추가
semnil5202 Feb 20, 2024
fef2b58
feat: 좋아요 토글 기능 구현
semnil5202 Feb 20, 2024
9024122
refactor: 스크랩 삭제 실패 시 디폴트 에러 메세지 수정
semnil5202 Feb 20, 2024
1d30324
refactor: API 변동사항 대응
semnil5202 Mar 5, 2024
cb37926
chore: 디자인 시스템 0.4.2 버전 업데이트
semnil5202 Mar 5, 2024
a4a2a97
fix: 좋아요 및 스크랩 SVG 컴포넌트 업데이트 오류 수정
semnil5202 Mar 5, 2024
0320a85
feat: 피드 내 모든 댓글 조회 기능 구현
semnil5202 Mar 5, 2024
008c4ba
feat: 댓글 버튼 및 textarea 포커스 시 스크롤 이동 및 textarea 확대 기능 추가
semnil5202 Mar 5, 2024
fdeadc9
feat: 대댓글 여부에 따른 UI 조건부 렌더링 기능 추가
semnil5202 Mar 5, 2024
834a9e5
refactor: 999개 이상 여부에 따른 조건부 UI 렌더링 기능 추가
semnil5202 Mar 5, 2024
9546071
fix: 대댓글 999개 초과 여부에 따른 조건부 UI 렌더링 오류 수정
semnil5202 Mar 5, 2024
51f4fef
feat: 댓글 입력창 클릭시 확장 및 프로필을 보여주는 기능 추가
semnil5202 Mar 6, 2024
0307be1
refactor: 댓글 버튼 포인터 기능 추가 및 클릭 시 textarea 포커스 기능 추가
semnil5202 Mar 6, 2024
7635f0b
refactor: 댓글 textarea 조작 관련 메서드 네이밍 수정
semnil5202 Mar 6, 2024
77aad6b
refactor: 이벤트 핸들러 메서드 분리
semnil5202 Mar 6, 2024
4a65c20
feat: 댓글 등록 기능 추가 및 보완
semnil5202 Mar 6, 2024
1055cf6
rename: query, mutation 디렉토리 분리 및 적용
semnil5202 Mar 6, 2024
9534a75
design: 댓글입력창과 댓글간 margin 조정
semnil5202 Mar 6, 2024
e913412
refactor: 서버 작업 중으로 인한 댓글 id 임시 상수값 지정
semnil5202 Mar 6, 2024
329cbff
refactor: get999plusCount 메서드 적용
semnil5202 Mar 6, 2024
75766bc
design: UI 오류 수정 및 폰트 무게 조정
semnil5202 Mar 6, 2024
657b2d5
design: 디자인 시안과 맞지 않는 UI 오류 수정
semnil5202 Mar 6, 2024
e393b73
refactor: post comment 성공 시 동작 로직 수정
semnil5202 Mar 6, 2024
7ae5aa5
refactor: context 훅 postfix 추가
semnil5202 Mar 6, 2024
4417114
fix: key 오류 수정
semnil5202 Mar 6, 2024
8e26570
feat: 대댓글 작성 기능 및 포커싱 기능 추가
semnil5202 Mar 6, 2024
366ba3f
feat: 대댓글 post 기능 추가
semnil5202 Mar 6, 2024
73a185a
refactor: 댓글 입력 창 확대시 내 정보로 가져오도록 변경
semnil5202 Mar 6, 2024
77c4a44
refactor: 댓글 및 대댓글 프로필 컴포넌트 분리 및 적용
semnil5202 Mar 6, 2024
9706006
refactor: Axios 함수 쿼리 및 뮤테이션 훅 내부로 위치
semnil5202 Mar 6, 2024
2e45c73
fix: Feed 페이지 오류 수정
semnil5202 Mar 6, 2024
a66d9e5
refactor: 댓글 전용 ProfileInfo와 댓글 작성 전용 ProfileInfo 컴포넌트 분리
semnil5202 Mar 7, 2024
3e30863
refactor: 댓글 및 대댓글 조회 API 변경사항 대응
semnil5202 Mar 7, 2024
ba0a78c
refactor: 불필요한 import 제거
semnil5202 Mar 7, 2024
248e2eb
refactor: 불필요한 console.log 제거
semnil5202 Mar 7, 2024
df671c8
refactor: 댓글 작성시 게시물 상세 댓글 개수 업데이트를 위해 게시글 상세 refetch 하도록 수정
semnil5202 Mar 7, 2024
e2e1b83
feat: 게시글 수정 및 삭제 기능 임시 추가
semnil5202 Mar 7, 2024
23c2fea
feat: 댓글 수정 입력창 구현
semnil5202 Mar 7, 2024
178fa8c
refactor: id 타입 변경에 따른 적용 및 메서드 명 수정 적용
semnil5202 Mar 7, 2024
c42e683
feat: 댓글 삭제 기능 구현
semnil5202 Mar 7, 2024
628d0ad
feat: 댓글 수정 기능 추가
semnil5202 Mar 7, 2024
5320154
refactor: id 타입 일괄 수정 및 적용
semnil5202 Mar 7, 2024
ec698ef
refactor: 댓글 작성시 Id 값 상수로 고정
semnil5202 Mar 7, 2024
3324b0e
feat: 댓글 무한 스크롤 조회 기능 구현
semnil5202 Mar 7, 2024
209cdaf
fix: 파일 대소문자 pr rebase 이후 import 경로 에러 수정
semnil5202 Mar 7, 2024
22d1464
refactor: API 변동에 따른 댓글 삭제 기능 보완 및 UI 업데이트 로직 추가
semnil5202 Mar 7, 2024
5619033
refactor: 댓글 및 대댓글 삭제 전 confirm 확인하는 로직 추가
semnil5202 Mar 7, 2024
6594d47
fix: 댓글 수정 시 포커싱이 안되는 오류 수정
semnil5202 Mar 7, 2024
d369e5e
refactor: 포커싱 로직 커스텀 훅으로 분리 및 재사용
semnil5202 Mar 7, 2024
97eceaa
refactor: context func 네이밍 수정
semnil5202 Mar 7, 2024
bdb04a2
refactor: navigator -> navigate로 네이밍 수정
semnil5202 Mar 8, 2024
af11088
feat: 댓글, 대댓글에 좋아요, 좋아요 해제 기능 추가
semnil5202 Mar 8, 2024
f9ccd16
refactor: id 값이 API 에 반영됨에 따라 key 값을 id 값으로 수정
semnil5202 Mar 8, 2024
8fb046a
refactor: query key 수정 'feed', 'detail'
semnil5202 Mar 8, 2024
93c4453
refactor: onSuccess mutate func 사용처에서 선언하여 사용
semnil5202 Mar 8, 2024
fb69e8f
rename: mutation 훅 mutation postfix 일괄 삭제 및 적용
semnil5202 Mar 8, 2024
acb852b
rename: 어색한 동사 순서 변경하여 네이밍 수정 및 일괄 적용
semnil5202 Mar 8, 2024
7c33f84
refactor: Base Url 수정
semnil5202 Mar 9, 2024
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
12 changes: 7 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@emotion/styled": "^11.11.0",
"@tanstack/react-query": "^5.17.19",
"axios": "^1.5.1",
"concept-be-design-system": "^0.4.1",
"concept-be-design-system": "^0.4.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.15.0",
Expand Down
8 changes: 5 additions & 3 deletions src/components/ProfileInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import styled from '@emotion/styled';
import { Text, TextDivider, Box, Flex } from 'concept-be-design-system';
import { Fragment } from 'react';

import { DEFAULT_IMAGE_URL } from '../constants';

interface Props {
imageUrl: string;
Expand All @@ -8,7 +11,6 @@ interface Props {
}

// TODO: 프로필 이미지 사진 오류 시 보여줄 기본 프로필 이미지 사진 URL
const DEFAULT_IMAGE_URL = '';

const ProfileInfo = ({ imageUrl, nickname, skillList }: Props) => {
return (
Expand All @@ -22,12 +24,12 @@ const ProfileInfo = ({ imageUrl, nickname, skillList }: Props) => {
</Text>
<Flex alignItems="center">
{skillList.map((skill, idx) => (
<>
<Fragment key={skill}>
<Text font="suit12r" color="b9">
{skill}
</Text>
{idx !== skillList.length - 1 && <TextDivider left={6} right={6} color="l2" />}
</>
</Fragment>
))}
</Flex>
</Flex>
Expand Down
5 changes: 5 additions & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
export const BASE_URL = 'http://conceptbe.kr:8080';

// 서버 작업으로 인한 임시 상수값
export const ROOT_COMMENT_ID = '0';

export const DEFAULT_IMAGE_URL = '';
130 changes: 34 additions & 96 deletions src/pages/FeedDetail/FeedDetail.page.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,18 @@
import styled from '@emotion/styled';
import {
Badge,
Divider,
Header,
Spacer,
Text,
TextDivider,
theme,
SVGTripleDots,
SVGFeedLike,
SVGFeedMessage,
SVGFeedPencil,
SVGFeedUnScrap,
SVGCancel,
Flex,
Box,
} from 'concept-be-design-system';
import { useParams } from 'react-router-dom';
import { Badge, Divider, Header, Spacer, Text, TextDivider, Flex, Box } from 'concept-be-design-system';
import { useNavigate, useParams } from 'react-router-dom';

import Comments from './components/Comments';
import useGetFeedDetail from './hooks/useGetFeedDetail';
import useHandleClickOutside from './hooks/useHandleClickOutside';
import ModifyDropdown from './components/ModifyDropdown';
import ReactionBar from './components/ReactionBar';
import { CommentFocusProvider } from './contexts/CommentFocusContext';
import useFeedDetailQuery from './hooks/queries/useFeedDetailQuery';
import ProfileInfo from '../../components/ProfileInfo';
import Back from '../../layouts/Back';
import Logo from '../../layouts/Logo';
import { formatCommentDate } from '../Feed/utils/formatCommentDate';

const FeedDetailPage = () => {
const navigate = useNavigate();
const { id: feedId } = useParams() as { id: string };
const {
imageUrl,
Expand All @@ -39,47 +25,36 @@ const FeedDetailPage = () => {
purposeList,
cooperationWay,
recruitmentPlace,
teamRecruitmentsList,
skillCategories,
likesCount,
commentsCount,
bookmarksCount,
hits,
commentParentResponses,
} = useGetFeedDetail(feedId);
owner,
ownerScrap,
ownerLike,
} = useFeedDetailQuery(feedId);

const { dropdownRef, isOpenModifyDropdown, toggleModifyDropdown } = useHandleClickOutside();
const onModifyFeedDetail = () => {
// 게시글 수정 로직 필요
};

const onDeleteFeedDetail = () => {
// 게시글 삭제 로직 필요
navigate(-1);
};

return (
<>
<CommentFocusProvider>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이게 어떤역할을 하나요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요 부분이 아래 세 가지 기능을 컨트롤 합니다.

  1. 댓글 입력창 상태 관리 및 포커싱, 포커싱 아웃 로직 관리 (댓글 맨 위 상단의 댓글 입력창)
  2. 대댓글 입력창 포커싱, 포커싱 아웃 로직 관리 (각 댓글 마다 생성 가능한 대댓글 입력창)
  3. 댓글 및 대댓글 수정 입력창 포커싱, 포커싱 아웃 로직 관리 (각 댓글, 대댓글 수정 시 보이는 입력창)

2번과 3번은 동일하게 생겼지만 1번이 조금 특이합니다. 1번의 경우에는 게시글 상세 통 틀어서 하나의 입력창이고 입력 값에 따라서 댓글창을 확장할지 축소할지 등의 로직이 추가됩니다. 그래서 컨텍스트 내부에 1번 입력창의 상태가 있고 2번, 3번 입력창은 각 컴포넌트의 로컬 상태로 관리됩니다. (각 댓글, 대댓글 마다 생성해야하므로)

위 기능을 관리하는 컨텍스트가 되겠습니다.

<Header main>
<Back />
<Logo />
<Box position="relative" ref={dropdownRef} cursor="pointer">
<SVGTripleDots onClick={toggleModifyDropdown} />
{isOpenModifyDropdown && (
<DropDownBox>
<Flex justifyContent="space-between" alignItems="center">
<Text font="suit12r" color="b6">
수정하기
</Text>
<SVGFeedPencil />
</Flex>
<Divider color="bg1" height={0.1} />
<Flex justifyContent="space-between" alignItems="center">
<Text font="suit12r" color="b6">
삭제하기
</Text>
<SVGCancel />
</Flex>
</DropDownBox>
)}
</Box>
<ModifyDropdown owner={owner} onEdit={onModifyFeedDetail} onDelete={onDeleteFeedDetail} />
</Header>

<Box padding="30px 22px 30px 22px" marginTop={48}>
<ProfileInfo imageUrl={imageUrl} nickname={nickname} skillList={skillList} />

<Spacer size={20} />

<Box>
<div>
<Text font="suit14sm" color="c1">
Expand Down Expand Up @@ -162,7 +137,7 @@ const FeedDetailPage = () => {
</Text>
<Spacer size={12} />
<Flex wrap="wrap" gap={6}>
{teamRecruitmentsList.map((badge) => (
{skillCategories.map((badge) => (
<Badge key={badge} fontColor="b4">
{badge}
</Badge>
Expand All @@ -171,60 +146,23 @@ const FeedDetailPage = () => {
</Box>

<Spacer size={35} />

<Divider color="l3" />

<Flex justifyContent="space-between" padding="18px 0">
<Flex alignItems="center" gap={4}>
<SVGFeedMessage />
<Text font="suit12r" color="b9">
댓글
</Text>
<Text font="suit12b" color="b9">
{commentsCount > 999 ? '999+' : commentsCount}
</Text>
</Flex>
<Flex alignItems="center" gap={4}>
<SVGFeedLike />
<Text font="suit12r" color="b9">
좋아요
</Text>
<Text font="suit12b" color="b9">
{likesCount > 999 ? '999+' : likesCount}
</Text>
</Flex>
<Flex alignItems="center" gap={4}>
<SVGFeedUnScrap />
<Text font="suit12r" color="b9">
스크랩
</Text>
<Text font="suit12b" color="b9">
{bookmarksCount > 999 ? '999+' : bookmarksCount}
</Text>
</Flex>
</Flex>
<ReactionBar
feedId={feedId}
commentsCount={commentsCount}
likesCount={likesCount}
bookmarksCount={bookmarksCount}
ownerScrap={ownerScrap}
ownerLike={ownerLike}
/>
</Box>

<Divider color="bg1" height={8} />

<Comments comments={commentParentResponses} />
</>
<Comments feedId={feedId} />
</CommentFocusProvider>
);
};

export default FeedDetailPage;

const DropDownBox = styled.div`
position: absolute;
display: flex;
flex-direction: column;
justify-content: space-around;
background-color: ${theme.color.w1};
width: 88px;
height: 70px;
border-radius: 6px;
padding: 10px;
top: 40px;
right: -6px;
box-shadow: 0px 6px 10px 0px rgba(0, 0, 0, 0.18);
`;
Loading