Skip to content

Commit

Permalink
[FE] feat: 리뷰 목록 페이지 기능 구현 (#90)
Browse files Browse the repository at this point in the history
* fix: stylelint를 통한 css 속성 정렬 기능 오류 수정

- stylelint 버전16과 충돌되는 플러그인 삭제 : stylelint-config-prettier, stylelint-prettier
- css 정렬에 필요하지 않은 플러그인 삭제 : stylelint-config-standard, stylelint-config-styled-componented, stylelint-webpack-plugin
- 추가로 설치한 플러그인: postcss-syntax, @stylelint/postcss-css-in-js
- stylelint 적용 script 추가
- .stylelintrc.json 수정 : css 관련 rule 설정

* refactor: stylelint 적용에 따른 css 속성 정렬

* fix : 절대 경로 사용 시 오류 수정

오류 : eslintimport/no-unresolved

* chore: eslintrc.cjs 에서 불필요한 코드 삭제

 node 환경 setting 삭제

* feat: DropDown 컴포넌트 구현

- 사용자 선택을 위한 `DropDown` 컴포넌트를 구현
- `onChange` 이벤트 핸들러와 `options` 배열을 사용하여 옵션을 동적으로 표시

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* chore: svg 아이콘 크기 수정

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* design: Topbar UI 수정

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* design: 버튼, 검색창 UI 수정 후 export

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* feat: ReviewPreviewCard 컴포넌트 구현

- 리뷰 미리보기 카드 컴포넌트 구현
- 리뷰어 그룹 이름, 생성일, 리뷰 내용 미리보기, 키워드, 공개 여부를 표시

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* chore: ReviewPreview 인터페이스 추가

- 리뷰 미리보기 데이터 구조를 정의하는 `ReviewPreview` 인터페이스를 추가했습니다.

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* feat: SearchSection 컴포넌트 구현

- 검색 입력창, 검색 버튼, 드롭다운을 포함하여 검색 기능을 구현

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* feat: ReviewPreviewListPage 구현 및 모의 데이터 추가

- `ReviewPreviewListPage` 컴포넌트 구현
  - `SearchSection`을 포함하여 검색 기능을 구현
  - `ReviewPreviewCard`를 사용하여 리뷰 목록을 표시
- 모의 데이터(`mockReviewPreviews`) 추가

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* chore: import 중복 및 순서 정리, ReviewPreviewListPage 라우트 추가

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* chore: 여러 개의 요소를 감싸기 때문에 Container로 변경

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* feat: 리뷰 목록 데이터를 서버에서 가져오기 위해 getReviewListApi 함수 추가

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* refactor: 상세 리뷰 불러오기 api 엔드포인트 수정

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

* refactor: 상세 리뷰 페이지 API 연동 부분 수정

Co-Authored-By: badahertz52 <[email protected]>
Co-Authored-By: ImxYJL <[email protected]>
Co-Authored-By: Fe <[email protected]>

---------

Co-authored-by: badahertz52 <[email protected]>
Co-authored-by: ImxYJL <[email protected]>
Co-authored-by: Fe <[email protected]>
  • Loading branch information
4 people authored Jul 25, 2024
1 parent 93e9022 commit 21447e1
Show file tree
Hide file tree
Showing 23 changed files with 458 additions and 52 deletions.
6 changes: 4 additions & 2 deletions frontend/src/apis/endpoints.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const endPoint = {
postingReview: `${process.env.API_BASE_URL}reviews`,
postingReview: `${process.env.API_BASE_URL}/reviews`,
gettingDetailedReview: (reviewId: number, memberId: number) =>
`${process.env.API_BASE_URL}reviews/${reviewId}?memberId=${memberId}`,
`${process.env.API_BASE_URL}/reviews/${reviewId}?memberId=${memberId}`,
gettingReviewList: (revieweeId: number, lastReviewId: number, memberId: number) =>
`${process.env.API_BASE_URL}/reviews?revieweeId=${revieweeId}&lastReviewId=${lastReviewId}&memberId=${memberId}`,
gettingInfoToWriteReview: (reviewerGroupId: number) => `/reviewer-groups/${reviewerGroupId}`,
gettingKeyword: `${process.env.API_BASE_URL}keywords`,
};
Expand Down
30 changes: 29 additions & 1 deletion frontend/src/apis/review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const postReviewApi = async ({ reviewData }: { reviewData: ReviewData })
return data;
};

// 상세리뷰
// 상세 리뷰
export const getDetailedReviewApi = async ({ reviewId, memberId }: { reviewId: number; memberId: number }) => {
const response = await fetch(endPoint.gettingDetailedReview(reviewId, memberId), {
method: 'GET',
Expand All @@ -49,3 +49,31 @@ export const getDetailedReviewApi = async ({ reviewId, memberId }: { reviewId: n
const data = await response.json();
return data;
};

// 리뷰 리스트
export const getReviewListApi = async ({
revieweeId,
lastReviewId,
memberId,
}: {
revieweeId: number;
lastReviewId: number;
memberId: number;
}) => {
const response = await fetch(
`/api/reviews?revieweeId=${revieweeId}&lastReviewId=${lastReviewId}&memberId=${memberId}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
},
);

if (!response.ok) {
throw new Error('리뷰 리스트를 불러오는 데 실패했습니다.');
}

const data = await response.json();
return data;
};
4 changes: 2 additions & 2 deletions frontend/src/assets/lock.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions frontend/src/assets/unLock.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions frontend/src/components/ReviewPreviewCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import GithubLogo from '@/assets/githubLogo.svg';
import Lock from '@/assets/lock.svg';
import UnLock from '@/assets/unLock.svg';

import * as S from './styles';

interface ReviewPreviewCardProps {
reviewerGroup: {
name: string;
};
createdAt: string;
contentPreview: string;
keywords: { id: number; content: string }[];
isPublic: boolean;
}

const ReviewPreviewCard = ({
reviewerGroup,
createdAt,
contentPreview,
keywords,
isPublic,
}: ReviewPreviewCardProps) => {
return (
<S.Layout>
<S.Header>
<S.HeaderContainer>
<div>
<img src={GithubLogo} />
</div>
<div>
<S.Title>{reviewerGroup.name}</S.Title>
<S.SubTitle>{createdAt}</S.SubTitle>
</div>
</S.HeaderContainer>
<S.Visibility>
<img src={isPublic ? UnLock : Lock} />
<span>{isPublic ? '공개' : '비공개'}</span>
</S.Visibility>
</S.Header>
<S.Main>
<span>{contentPreview}</span>
<S.Keyword>
{keywords.map((keyword) => (
<div key={keyword.id}>{keyword.content}</div>
))}
</S.Keyword>
</S.Main>
</S.Layout>
);
};

export default ReviewPreviewCard;
85 changes: 85 additions & 0 deletions frontend/src/components/ReviewPreviewCard/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import styled from '@emotion/styled';

export const Layout = styled.div`
display: flex;
flex-direction: column;
width: 100%;
border: 1px solid ${({ theme }) => theme.colors.lightGray};
border-radius: 8px;
&:hover {
cursor: pointer;
border: 1px solid ${({ theme }) => theme.colors.primaryHover};
& > div:first-of-type {
background-color: ${({ theme }) => theme.colors.primaryHover};
}
}
`;

export const Header = styled.div`
display: flex;
justify-content: space-between;
height: 6rem;
padding: 1rem 3rem;
background-color: ${({ theme }) => theme.colors.lightGray};
border-top-left-radius: 0.8rem;
border-top-right-radius: 0.8rem;
`;

export const HeaderContainer = styled.div`
display: flex;
gap: 1rem;
img {
width: 4rem;
}
`;

export const Title = styled.div`
font-size: 1.6rem;
font-weight: 700;
`;

export const SubTitle = styled.div`
font-size: 1.2rem;
`;

export const Visibility = styled.div`
display: flex;
gap: 0.6rem;
align-items: center;
font-size: 1.6rem;
font-weight: 700;
img {
width: 2rem;
}
`;

export const Main = styled.div`
display: flex;
flex-direction: column;
gap: 2rem;
padding: 2rem 3rem;
font-size: 1.6rem;
`;

export const Keyword = styled.div`
display: flex;
gap: 3rem;
align-items: center;
font-size: 1.4rem;
div {
padding: 0.5rem 3rem;
background-color: ${({ theme }) => theme.colors.primaryHover};
border-radius: 0.8rem;
}
`;
2 changes: 1 addition & 1 deletion frontend/src/components/common/Button/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const Button = styled.button<{ buttonType: ButtonType }>`
width: 10rem;
height: 4rem;
padding: 2rem;
padding: 1rem 2rem;
border: 0.1rem solid ${({ theme }) => theme.colors.primary};
border-radius: 0.8rem;
Expand Down
24 changes: 24 additions & 0 deletions frontend/src/components/common/DropDown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as S from './styles';

interface DropDownProps {
onChange: (value: string) => void;
options: string[];
}

const DropDown = ({ onChange, options }: DropDownProps) => {
const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
onChange(e.target.value);
};

return (
<S.Container onChange={handleChange}>
{options.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</S.Container>
);
};

export default DropDown;
11 changes: 11 additions & 0 deletions frontend/src/components/common/DropDown/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import styled from '@emotion/styled';

export const Container = styled.select`
width: 12rem;
padding: 8px;
font-size: 1.6rem;
border: 1px solid ${({ theme }) => theme.colors.placeholder};
border-radius: 0.8rem;
`;
7 changes: 6 additions & 1 deletion frontend/src/components/common/SearchInput/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ export const Input = styled.input<InputProps>`
padding: 1.6rem;
border: 1px solid ${({ theme }) => theme.colors.black};
border-radius: 1.5rem;
border-radius: 0.8rem;
&::placeholder {
font-size: 1.2rem;
color: ${({ theme }) => theme.colors.placeholder};
}
`;
2 changes: 2 additions & 0 deletions frontend/src/components/common/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export { default as Button } from './Button';
export { default as DropDown } from './DropDown';
export { default as SearchInput } from './SearchInput';
export { default as ProjectImg } from './ProjectImg';
export { default as ReviewDate } from './ReviewDate';
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/layouts/Sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import * as S from './styles';
const PATH = {
myPage: '/user/mypage',
reviewWriting: '/user/review-writing',
allReview: '/user/all-review',
detailedReview: '/user/detailed-review/0?memberId=1',
reviewPreviewList: '/user/review-preview-list',
detailedReview: '/user/detailed-review',
reviewGroupManagement: '/user/review-group-management',
};

Expand All @@ -25,7 +25,7 @@ const Sidebar = ({ isSidebarOpen, closeSidebar }: SidebarProps) => {
const menuItems = [
{ path: PATH.myPage, label: PAGE.myPage },
{ path: PATH.reviewWriting, label: PAGE.reviewWriting },
{ path: PATH.allReview, label: PAGE.allReview },
{ path: PATH.reviewPreviewList, label: PAGE.reviewPreviewList },
{ path: PATH.detailedReview, label: PAGE.detailedReview },
{ path: PATH.reviewGroupManagement, label: PAGE.reviewGroupManagement },
];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import styled from '@emotion/styled';

export const HamburgerButton = styled.button`
width: 3.7rem;
height: 3.7rem;
width: 2.3rem;
height: 2.3rem;
img {
width: 100%;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/layouts/Topbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const Topbar = ({ openSidebar }: TopbarProps) => {
<Logo />
</S.Container>
<S.Container>
<SearchInput $width="15rem" $height="3.6rem" placeholder={USER_SEARCH_PLACE_HOLDER} />
<SearchInput $width="30rem" $height="3.6rem" placeholder={USER_SEARCH_PLACE_HOLDER} />
<S.UserProfile src={UserProfileIcon} alt="로그인한 사용자 깃허브 프로필" />
</S.Container>
</S.Layout>
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/components/layouts/Topbar/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ export const Layout = styled.section`
box-sizing: border-box;
width: 100%;
height: 8rem;
padding: 1.8rem 2.5rem;
height: 7rem;
padding: 2rem 2.5rem;
border-bottom: 0.1rem solid ${({ theme }) => theme.colors.lightGray};
`;

export const Container = styled.div`
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/constants/page.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const PAGE = {
myPage: '마이페이지',
reviewWriting: '리뷰 작성하기',
allReview: '전체 리뷰 보기',
reviewPreviewList: '전체 리뷰 보기',
detailedReview: '상세 리뷰 보기',
reviewGroupManagement: '리뷰 그룹 관리',
};
8 changes: 4 additions & 4 deletions frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import App from '@/App';

import DetailedReviewPage from './pages/DetailedReviewPage';
import ReviewPreviewListPage from './pages/ReviewPreviewListPage';
import ReviewWritingPage from './pages/ReviewWriting';
import ReviewWritingCompletePage from './pages/ReviewWritingCompletePage';
import globalStyles from './styles/globalStyles';
import theme from './styles/theme';

Expand All @@ -25,11 +25,11 @@ const router = createBrowserRouter([
element: <ReviewWritingPage />,
},
{
path: 'user/review-writing-complete',
element: <ReviewWritingCompletePage />,
path: 'user/review-preview-list',
element: <ReviewPreviewListPage />,
},
{
path: 'user/detailed-review/:id',
path: 'user/detailed-review',
element: <DetailedReviewPage />,
},
],
Expand Down
Loading

0 comments on commit 21447e1

Please sign in to comment.