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

[FE] feat: 리뷰 상세 페이지 구현 #762

Merged
merged 12 commits into from
Oct 16, 2023
9 changes: 9 additions & 0 deletions frontend/.storybook/preview-body.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@
d="M3 4V1h2v3h3v2H5v3H3V6H0V4m6 6V7h3V4h7l1.8 2H21c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2V10m10 9c4.45 0 6.69-5.38 3.54-8.54C13.39 7.31 8 9.55 8 14c0 2.76 2.24 5 5 5m-3.2-5c0 2.85 3.45 4.28 5.46 2.26c2.02-2.01.59-5.46-2.26-5.46A3.21 3.21 0 0 0 9.8 14Z"
/>
</symbol>
<symbol viewBox="0 0 24 24" id="link">
<g fill="currentColor">
<path
d="M15.729 3.884c1.434-1.44 3.532-1.47 4.693-.304c1.164 1.168 1.133 3.28-.303 4.72l-2.423 2.433a.75.75 0 0 0 1.062 1.059l2.424-2.433c1.911-1.919 2.151-4.982.303-6.838c-1.85-1.857-4.907-1.615-6.82.304L9.819 7.692c-1.911 1.919-2.151 4.982-.303 6.837a.75.75 0 1 0 1.063-1.058c-1.164-1.168-1.132-3.28.303-4.72l4.848-4.867Z"
></path>
<path
d="M14.485 9.47a.75.75 0 0 0-1.063 1.06c1.164 1.168 1.133 3.279-.303 4.72l-4.847 4.866c-1.435 1.44-3.533 1.47-4.694.304c-1.164-1.168-1.132-3.28.303-4.72l2.424-2.433a.75.75 0 0 0-1.063-1.059l-2.424 2.433c-1.911 1.92-2.151 4.982-.303 6.838c1.85 1.858 4.907 1.615 6.82-.304l4.847-4.867c1.911-1.918 2.151-4.982.303-6.837Z"
></path>
</g>
<symbol id="plane" width="32" height="32" viewBox="0 0 256 256">
<path
d="M232 127.89a16 16 0 0 1-8.18 14L55.91 237.9A16.14 16.14 0 0 1 48 240a16 16 0 0 1-15.05-21.34l27.35-79.95a4 4 0 0 1 3.79-2.71H136a8 8 0 0 0 8-8.53a8.19 8.19 0 0 0-8.26-7.47H64.16a4 4 0 0 1-3.79-2.7l-27.44-80a16 16 0 0 1 22.92-19.23l168 95.89a16 16 0 0 1 8.15 13.93Z"
Expand Down
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"test:coverage": "jest --watchAll --coverage"
},
"dependencies": {
"@fun-eat/design-system": "^0.3.13",
"@fun-eat/design-system": "^0.3.15",
"@tanstack/react-query": "^4.32.6",
"@tanstack/react-query-devtools": "^4.32.6",
"dayjs": "^1.11.9",
Expand Down Expand Up @@ -46,6 +46,7 @@
"@typescript-eslint/eslint-plugin": "^5.60.1",
"@typescript-eslint/parser": "^5.60.1",
"babel-plugin-styled-components": "^2.1.4",
"browser-image-compression": "^2.0.2",
"copy-webpack-plugin": "^11.0.0",
"dotenv-webpack": "^8.0.1",
"eslint": "^8.44.0",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/apis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export const memberApi = new ApiClient('/members');
export const recipeApi = new ApiClient('/recipes');
export const searchApi = new ApiClient('/search');
export const logoutApi = new ApiClient('/logout');
export const reviewApi = new ApiClient('/reviews');
2 changes: 1 addition & 1 deletion frontend/src/components/Common/Loading/Loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const rotate = keyframes`
}

100% {
transform: rotate(-360deg);
transform: rotate(360deg);
Copy link
Collaborator

Choose a reason for hiding this comment

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

⏰👍

}
`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ type Story = StoryObj<typeof SectionTitle>;
export const Default: Story = {
args: {
name: '사이다',
bookmark: false,
},
};

export const Bookmarked: Story = {
args: {
name: '사이다',
bookmark: true,
},
};
31 changes: 16 additions & 15 deletions frontend/src/components/Common/SectionTitle/SectionTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { Button, Heading, theme } from '@fun-eat/design-system';
import { Button, Heading, Link, theme } from '@fun-eat/design-system';
import { Link as RouterLink } from 'react-router-dom';
import styled from 'styled-components';

import { SvgIcon } from '@/components/Common';
import { useRoutePage } from '@/hooks/common';

interface SectionTitleProps {
name: string;
bookmark?: boolean;
link?: string;
}
Comment on lines -9 to +10
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍


const SectionTitle = ({ name, bookmark = false }: SectionTitleProps) => {
const SectionTitle = ({ name, link }: SectionTitleProps) => {
const { routeBack } = useRoutePage();

return (
Expand All @@ -18,18 +19,15 @@ const SectionTitle = ({ name, bookmark = false }: SectionTitleProps) => {
<Button type="button" variant="transparent" onClick={routeBack} aria-label="뒤로 가기">
<SvgIcon variant="arrow" color={theme.colors.gray5} width={15} height={15} />
</Button>
<Heading size="xl" css="margin-left: 20px">
{name}
</Heading>
{link ? (
<Link as={RouterLink} to={link} block>
<ProductName size="xl">{name}</ProductName>
</Link>
) : (
<ProductName size="xl">{name}</ProductName>
)}
{link && <SvgIcon variant="link" width={20} height={20} />}
</SectionTitleWrapper>
{bookmark && (
<Button type="button" customWidth="32px" variant="transparent" aria-label="북마크">
<SvgIcon
variant={bookmark ? 'bookmarkFilled' : 'bookmark'}
color={bookmark ? theme.colors.primary : theme.colors.gray5}
/>
</Button>
)}
</SectionTitleContainer>
);
};
Expand All @@ -45,9 +43,12 @@ const SectionTitleContainer = styled.div`
const SectionTitleWrapper = styled.div`
display: flex;
align-items: center;
column-gap: 16px;

svg {
padding-top: 2px;
}
`;

const ProductName = styled(Heading)`
margin: 0 5px 0 16px;
`;
1 change: 1 addition & 0 deletions frontend/src/components/Common/Svg/SvgIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const SVG_ICON_VARIANTS = [
'plus',
'pencil',
'camera',
'link',
'plane',
] as const;
export type SvgIconVariant = (typeof SVG_ICON_VARIANTS)[number];
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/components/Common/Svg/SvgSprite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ const SvgSprite = () => {
<symbol viewBox="0 0 24 24" id="camera">
<path d="M3 4V1h2v3h3v2H5v3H3V6H0V4m6 6V7h3V4h7l1.8 2H21c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2V10m10 9c4.45 0 6.69-5.38 3.54-8.54C13.39 7.31 8 9.55 8 14c0 2.76 2.24 5 5 5m-3.2-5c0 2.85 3.45 4.28 5.46 2.26c2.02-2.01.59-5.46-2.26-5.46A3.21 3.21 0 0 0 9.8 14Z" />
</symbol>
<symbol viewBox="0 0 24 24" id="link">
<g fill="currentColor">
<path d="M15.729 3.884c1.434-1.44 3.532-1.47 4.693-.304c1.164 1.168 1.133 3.28-.303 4.72l-2.423 2.433a.75.75 0 0 0 1.062 1.059l2.424-2.433c1.911-1.919 2.151-4.982.303-6.838c-1.85-1.857-4.907-1.615-6.82.304L9.819 7.692c-1.911 1.919-2.151 4.982-.303 6.837a.75.75 0 1 0 1.063-1.058c-1.164-1.168-1.132-3.28.303-4.72l4.848-4.867Z" />
<path d="M14.485 9.47a.75.75 0 0 0-1.063 1.06c1.164 1.168 1.133 3.279-.303 4.72l-4.847 4.866c-1.435 1.44-3.533 1.47-4.694.304c-1.164-1.168-1.132-3.28.303-4.72l2.424-2.433a.75.75 0 0 0-1.063-1.059l-2.424 2.433c-1.911 1.92-2.151 4.982-.303 6.838c1.85 1.858 4.907 1.615 6.82-.304l4.847-4.867c1.911-1.918 2.151-4.982.303-6.837Z" />
</g>
</symbol>
<symbol id="plane" viewBox="0 0 256 256">
<path d="M232 127.89a16 16 0 0 1-8.18 14L55.91 237.9A16.14 16.14 0 0 1 48 240a16 16 0 0 1-15.05-21.34l27.35-79.95a4 4 0 0 1 3.79-2.71H136a8 8 0 0 0 8-8.53a8.19 8.19 0 0 0-8.26-7.47H64.16a4 4 0 0 1-3.79-2.7l-27.44-80a16 16 0 0 1 22.92-19.23l168 95.89a16 16 0 0 1 8.15 13.93Z" />
</symbol>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,8 @@ const MemberReviewList = ({ isMemberPage = false }: MemberReviewListProps) => {
<MemberReviewListWrapper>
{reviewsToDisplay.map((reviewRanking) => (
<li key={reviewRanking.reviewId}>
<Link
as={RouterLink}
to={`${PATH.PRODUCT_LIST}/${reviewRanking.categoryType}/${reviewRanking.productId}`}
block
>
<ReviewRankingItem reviewRanking={reviewRanking} />
<Link as={RouterLink} to={`${PATH.REVIEW}/${reviewRanking.reviewId}`} block>
<ReviewRankingItem reviewRanking={reviewRanking} isMemberPage />
</Link>
</li>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import type { ReviewRanking } from '@/types/ranking';

interface ReviewRankingItemProps {
reviewRanking: ReviewRanking;
isMemberPage?: boolean;
}

const ReviewRankingItem = ({ reviewRanking }: ReviewRankingItemProps) => {
const ReviewRankingItem = ({ reviewRanking, isMemberPage = false }: ReviewRankingItemProps) => {
const { productName, content, rating, favoriteCount } = reviewRanking;

return (
<ReviewRankingItemContainer>
<ReviewRankingItemContainer isMemberPage={isMemberPage}>
<Text size="sm" weight="bold">
{productName}
</Text>
Expand Down Expand Up @@ -41,13 +42,14 @@ const ReviewRankingItem = ({ reviewRanking }: ReviewRankingItemProps) => {

export default memo(ReviewRankingItem);

const ReviewRankingItemContainer = styled.div`
const ReviewRankingItemContainer = styled.div<{ isMemberPage: boolean }>`
display: flex;
flex-direction: column;
gap: 4px;
padding: 12px;
border: 1px solid ${({ theme }) => theme.borderColors.disabled};
border-radius: ${({ theme }) => theme.borderRadius.sm};
border: ${({ isMemberPage, theme }) => (isMemberPage ? 'none' : `1px solid ${theme.borderColors.disabled}`)};
border-bottom: ${({ theme }) => `1px solid ${theme.borderColors.disabled}`};
border-radius: ${({ isMemberPage, theme }) => (isMemberPage ? 0 : theme.borderRadius.sm)};
`;

const ReviewText = styled(Text)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const ReviewRankingList = ({ isHomePage = false }: ReviewRankingListProps) => {
<li key={reviewRanking.reviewId}>
<Link
as={RouterLink}
to={`${PATH.PRODUCT_LIST}/${reviewRanking.categoryType}/${reviewRanking.productId}`}
to={`${PATH.REVIEW}/${reviewRanking.reviewId}`}
onClick={handleReviewRankingLinkClick}
block
>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/constants/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export const PATH = {
PRODUCT_LIST: '/products',
MEMBER: '/members',
RECIPE: '/recipes',
REVIEW: '/reviews',
LOGIN: '/login',
} as const;
1 change: 1 addition & 0 deletions frontend/src/hooks/queries/review/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as useReviewTagsQuery } from './useReviewTagsQuery';
export { default as useReviewFavoriteMutation } from './useReviewFavoriteMutation';
export { default as useReviewRegisterFormMutation } from './useReviewRegisterFormMutation';
export { default as useReviewDetailQuery } from './useReviewDetailQuery';
16 changes: 16 additions & 0 deletions frontend/src/hooks/queries/review/useReviewDetailQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useSuspendedQuery } from '../useSuspendedQuery';

import { reviewApi } from '@/apis';
import type { ReviewDetailResponse } from '@/types/response';

const fetchReviewDetail = async (reviewId: number) => {
const response = await reviewApi.get({ params: `/${reviewId}` });
const data: ReviewDetailResponse = await response.json();
return data;
};

const useReviewDetailQuery = (reviewId: number) => {
return useSuspendedQuery(['review'], () => fetchReviewDetail(reviewId));
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기 쿼리키에 reviewId도 들어가야 할 것 같아요!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

얍! product detail처럼 'detail' key도 추가했습니다~


export default useReviewDetailQuery;
1 change: 0 additions & 1 deletion frontend/src/mocks/data/productDetail.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"image": "https://i.namu.wiki/i/9wnvUaEa1EkDqG-M0Pbwfdf19FJQQXV_-bnlU2SYaNcG05y2wbabiIrfrGES1M4xSgDjY39RwOvLNggDd3Huuw.webp",
"content": "할머니가 먹을 거 같은 맛입니다.\n1960년 전쟁 때 맛 보고 싶었는데 그때는 너무 가난해서 먹을 수 없었는데, 맛있어요.",
"averageRating": 4.5,
"bookmark": false,
"reviewCount": 100,
"tags": [
{
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/mocks/data/productDetails.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"image": "https://github.com/woowacourse-teams/2023-fun-eat/assets/78616893/1f0fd418-131c-4cf8-b540-112d762b7c34",
"content": "할머니가 먹을 거 같은 맛입니다.\n1960년 전쟁 때 맛 보고 싶었는데 그때는 너무 가난해서 먹을 수 없었는데, 맛있어요.",
"averageRating": 4.5,
"bookmark": false,
"reviewCount": 100,
"tags": [
{
Expand All @@ -33,7 +32,6 @@
"image": "https://github.com/woowacourse-teams/2023-fun-eat/assets/78616893/1f0fd418-131c-4cf8-b540-112d762b7c34",
"content": "할머니가 먹을 거 같은 맛입니다. 1960년 전쟁 때 맛 보고 싶었는데 그때는 너무 가난해서 먹을 수 없었는데, 맛있어요.",
"averageRating": 4.0,
"bookmark": true,
"reviewCount": 55,
"tags": [
{
Expand Down
29 changes: 29 additions & 0 deletions frontend/src/mocks/data/reviewDetail.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"reviews": {
"id": 1,
"userName": "펀잇",
"profileImage": "https://github.com/woowacourse-teams/2023-fun-eat/assets/78616893/1f0fd418-131c-4cf8-b540-112d762b7c34",
"image": "https://i.namu.wiki/i/9wnvUaEa1EkDqG-M0Pbwfdf19FJQQXV_-bnlU2SYaNcG05y2wbabiIrfrGES1M4xSgDjY39RwOvLNggDd3Huuw.webp",
"rating": 4.5,
"tags": [
{
"id": 5,
"name": "단짠단짠",
"tagType": "TASTE"
},
{
"id": 1,
"name": "망고망고",
"tagType": "TASTE"
}
],
"content": "맛있어용~!~!",
"rebuy": true,
"favoriteCount": 1320,
"favorite": true,
"createdAt": "2023-10-13T00:00:00",
"categoryType": "food",
"productId": 1,
"productName": "칠성 사이다"
}
}
5 changes: 5 additions & 0 deletions frontend/src/mocks/handlers/reviewHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { rest } from 'msw';

import { isReviewSortOption, isSortOrder } from './utils';
import mockReviewDetail from '../data/reviewDetail.json';
import mockReviewRanking from '../data/reviewRankingList.json';
import mockReviews from '../data/reviews.json';
import mockReviewTags from '../data/reviewTagList.json';
Expand Down Expand Up @@ -73,4 +74,8 @@ export const reviewHandlers = [
rest.get('/api/tags', (_, res, ctx) => {
return res(ctx.status(200), ctx.json(mockReviewTags));
}),

rest.get('/api/reviews/:reviewId', (_, res, ctx) => {
return res(ctx.status(200), ctx.json(mockReviewDetail));
}),
];
4 changes: 2 additions & 2 deletions frontend/src/pages/ProductDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const ProductDetailPage = () => {
return null;
}

const { name, bookmark, reviewCount } = productDetail;
const { name, reviewCount } = productDetail;

const tabMenus = [`리뷰 ${reviewCount}`, '꿀조합'];
const sortOptions = isReviewTab ? REVIEW_SORT_OPTIONS : RECIPE_SORT_OPTIONS;
Expand Down Expand Up @@ -84,7 +84,7 @@ export const ProductDetailPage = () => {

return (
<ProductDetailPageContainer ref={productDetailPageRef}>
<SectionTitle name={name} bookmark={bookmark} />
<SectionTitle name={name} />
<Spacing size={36} />
<ProductDetailItem category={category} productDetail={productDetail} />
<Spacing size={30} />
Expand Down
Loading
Loading