diff --git a/.storybook/preview-body.html b/.storybook/preview-body.html index 23699d190..ba12aafb9 100644 --- a/.storybook/preview-body.html +++ b/.storybook/preview-body.html @@ -276,10 +276,19 @@ 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" > - - + + + + + + + + + { - const { routeBack } = useRoutePage(); - +const SectionTitle = ({ name, hasSearchLink }: SectionTitleProps) => { return ( - - - - - - {link ? ( - - {name} - - ) : ( - {name} - )} - {link && } - - + + + + + + + {name} + + + {hasSearchLink && ( + + + + )} + ); }; export default SectionTitle; - -const SectionTitleContainer = styled.div` - display: flex; - justify-content: space-between; - align-items: center; -`; - -const SectionTitleWrapper = styled.div` - display: flex; - align-items: center; - - svg { - padding-top: 2px; - } -`; - -const ProductName = styled(Heading)` - margin: 0 5px 0 16px; -`; diff --git a/src/components/Common/SectionTitle/sectionTitle.css.ts b/src/components/Common/SectionTitle/sectionTitle.css.ts new file mode 100644 index 000000000..be0030e95 --- /dev/null +++ b/src/components/Common/SectionTitle/sectionTitle.css.ts @@ -0,0 +1,13 @@ +import { style } from '@vanilla-extract/css'; + +export const container = style({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', +}); + +export const wrapper = style({ + display: 'flex', + gap: 18, + alignItems: 'flex-start', +}); diff --git a/src/components/Common/Svg/SvgIcon.tsx b/src/components/Common/Svg/SvgIcon.tsx index 4b6c0796b..305891eb8 100644 --- a/src/components/Common/Svg/SvgIcon.tsx +++ b/src/components/Common/Svg/SvgIcon.tsx @@ -43,6 +43,7 @@ export const SVG_ICON_VARIANTS = [ 'arrowUpDown', 'heartEmpty', 'heartFilled', + 'box', 'close2', 'disk', ] as const; diff --git a/src/components/Common/Svg/SvgSprite.tsx b/src/components/Common/Svg/SvgSprite.tsx index 922b6ec46..106e7367c 100644 --- a/src/components/Common/Svg/SvgSprite.tsx +++ b/src/components/Common/Svg/SvgSprite.tsx @@ -243,8 +243,19 @@ const SvgSprite = () => { - - + + + + + + + + + diff --git a/src/components/Product/ProductOverviewList/ProductOverviewList.tsx b/src/components/Product/ProductOverviewList/ProductOverviewList.tsx index 66d615cb7..eb91ba36b 100644 --- a/src/components/Product/ProductOverviewList/ProductOverviewList.tsx +++ b/src/components/Product/ProductOverviewList/ProductOverviewList.tsx @@ -8,10 +8,10 @@ import type { Product } from '@/types/product'; interface ProductOverviewListProps { products: Product[]; - isSearchPage?: boolean; + hasBorder?: boolean; } -const ProductOverviewList = ({ products, isSearchPage = false }: ProductOverviewListProps) => { +const ProductOverviewList = ({ products, hasBorder = false }: ProductOverviewListProps) => { return ( {products.map(({ id, image, name, price, averageRating }) => ( @@ -19,7 +19,7 @@ const ProductOverviewList = ({ products, isSearchPage = false }: ProductOverview - {isSearchPage && ( + {hasBorder && ( <> diff --git a/src/components/Recipe/CommentForm/CommentForm.tsx b/src/components/Recipe/CommentForm/CommentForm.tsx index 114322c56..b162150c6 100644 --- a/src/components/Recipe/CommentForm/CommentForm.tsx +++ b/src/components/Recipe/CommentForm/CommentForm.tsx @@ -1,11 +1,14 @@ -import { Button, Spacing, Text, Textarea, useTheme, useToastActionContext } from '@fun-eat/design-system'; +import { useToastActionContext } from '@fun-eat/design-system'; import type { ChangeEventHandler, FormEventHandler, RefObject } from 'react'; -import { useState } from 'react'; -import styled from 'styled-components'; +import { useRef, useState } from 'react'; -import { SvgIcon } from '@/components/Common'; +import { commentForm, commentTextarea, container, profileImage, sendButton } from './commentForm.css'; + +import { SvgIcon, Text } from '@/components/Common'; import { useScroll } from '@/hooks/common'; +import { useMemberQuery } from '@/hooks/queries/members'; import { useRecipeCommentMutation } from '@/hooks/queries/recipe'; +import { vars } from '@/styles/theme.css'; interface CommentFormProps { recipeId: number; @@ -15,16 +18,27 @@ interface CommentFormProps { const MAX_COMMENT_LENGTH = 200; const CommentForm = ({ recipeId, scrollTargetRef }: CommentFormProps) => { + const { data: member } = useMemberQuery(); + const [commentValue, setCommentValue] = useState(''); const { mutate } = useRecipeCommentMutation(recipeId); - const theme = useTheme(); const { toast } = useToastActionContext(); const { scrollToPosition } = useScroll(); + const textAreaRef = useRef(null); + + const autoResizeTextarea = () => { + if (textAreaRef.current) { + textAreaRef.current.style.height = 'auto'; + textAreaRef.current.style.height = textAreaRef.current.scrollHeight + 'px'; + } + }; + const handleCommentInput: ChangeEventHandler = (e) => { setCommentValue(e.target.value); + autoResizeTextarea(); }; const handleSubmitComment: FormEventHandler = (e) => { @@ -51,54 +65,40 @@ const CommentForm = ({ recipeId, scrollTargetRef }: CommentFormProps) => { }; return ( - - - - - + + <> + + - - - - - {commentValue.length}자 / {MAX_COMMENT_LENGTH}자 - - + + {commentValue.length}/200 + + + + + + > + ); }; export default CommentForm; - -const CommentFormContainer = styled.div` - position: fixed; - bottom: 0; - width: calc(100% - 40px); - max-width: 540px; - padding: 16px 0; - background: ${({ theme }) => theme.backgroundColors.default}; -`; - -const Form = styled.form` - display: flex; - gap: 4px; - justify-content: space-around; - align-items: center; -`; - -const CommentTextarea = styled(Textarea)` - height: 50px; - padding: 8px; -`; - -const SubmitButton = styled(Button)` - cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')}; -`; diff --git a/src/components/Recipe/CommentForm/commentForm.css.ts b/src/components/Recipe/CommentForm/commentForm.css.ts new file mode 100644 index 000000000..3ebe1b3fc --- /dev/null +++ b/src/components/Recipe/CommentForm/commentForm.css.ts @@ -0,0 +1,43 @@ +import { vars } from '@/styles/theme.css'; +import { style } from '@vanilla-extract/css'; + +export const container = style({ + display: 'flex', + gap: 8, + alignItems: 'flex-end', + marginBottom: 24, +}); + +export const commentForm = style({ + display: 'flex', + gap: 8, + alignItems: 'flex-end', + width: '100%', + padding: '6px 16px 9px 16px', + background: vars.colors.background.category, + borderRadius: 20, +}); + +export const commentTextarea = style({ + width: '100%', + height: '100%', + border: 'none', + outline: 'none', + background: 'none', + fontSize: '1.4rem', + resize: 'none', + + selectors: { + '&:placeholder': { + color: '#808080', + }, + }, +}); + +export const profileImage = style({ + borderRadius: '50%', +}); + +export const sendButton = style({ + display: 'inherit', +}); diff --git a/src/components/Recipe/CommentItem/CommentItem.stories.tsx b/src/components/Recipe/CommentItem/CommentItem.stories.tsx new file mode 100644 index 000000000..70bf1f9a6 --- /dev/null +++ b/src/components/Recipe/CommentItem/CommentItem.stories.tsx @@ -0,0 +1,18 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import CommentItem from './CommentItem'; + +import comments from '@/mocks/data/comments.json'; + +const meta: Meta = { + title: 'recipe/CommentItem', + component: CommentItem, + args: { + recipeComment: comments.comments[0], + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/src/components/Recipe/CommentItem/CommentItem.tsx b/src/components/Recipe/CommentItem/CommentItem.tsx index 121af50c6..18ce993f2 100644 --- a/src/components/Recipe/CommentItem/CommentItem.tsx +++ b/src/components/Recipe/CommentItem/CommentItem.tsx @@ -1,46 +1,25 @@ -import { Divider, Spacing, Text, useTheme } from '@fun-eat/design-system'; -import styled from 'styled-components'; +import { container, nickname } from './commentItem.css'; -import { MemberImage } from '@/components/Members'; +import { Text } from '@/components/Common'; import type { Comment } from '@/types/recipe'; -import { getFormattedDate } from '@/utils/date'; interface CommentItemProps { recipeComment: Comment; } const CommentItem = ({ recipeComment }: CommentItemProps) => { - const theme = useTheme(); - const { author, comment, createdAt } = recipeComment; + const { author, comment } = recipeComment; return ( - <> - - - - - {author.nickname} 님 - - - {getFormattedDate(createdAt)} - - - - {comment} - - - > + + + {author.nickname} + + + {comment} + + ); }; export default CommentItem; - -const AuthorWrapper = styled.div` - display: flex; - gap: 12px; - align-items: center; -`; - -const CommentContent = styled(Text)` - margin: 16px 0; -`; diff --git a/src/components/Recipe/CommentItem/commentItem.css.ts b/src/components/Recipe/CommentItem/commentItem.css.ts new file mode 100644 index 000000000..ccd91c2f8 --- /dev/null +++ b/src/components/Recipe/CommentItem/commentItem.css.ts @@ -0,0 +1,10 @@ +import { style } from '@vanilla-extract/css'; + +export const container = style({ + display: 'flex', + gap: 6, +}); + +export const nickname = style({ + whiteSpace: 'nowrap', +}); diff --git a/src/components/Recipe/CommentList/CommentList.stories.tsx b/src/components/Recipe/CommentList/CommentList.stories.tsx new file mode 100644 index 000000000..2f62a5d4e --- /dev/null +++ b/src/components/Recipe/CommentList/CommentList.stories.tsx @@ -0,0 +1,16 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import CommentList from './CommentList'; + +const meta: Meta = { + title: 'recipe/CommentList', + component: CommentList, + args: { + recipeId: 1, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/src/components/Recipe/CommentList/CommentList.tsx b/src/components/Recipe/CommentList/CommentList.tsx index d44f33c34..0fd2a15d0 100644 --- a/src/components/Recipe/CommentList/CommentList.tsx +++ b/src/components/Recipe/CommentList/CommentList.tsx @@ -1,6 +1,6 @@ -import { Heading, Spacing, Text, theme } from '@fun-eat/design-system'; import { useRef } from 'react'; +import { commentCount } from './commentList.css'; import CommentItem from '../CommentItem/CommentItem'; import { useIntersectionObserver } from '@/hooks/common'; @@ -21,11 +21,7 @@ const CommentList = ({ recipeId }: CommentListProps) => { return ( <> - - 댓글 ({totalElements}개) - - - {totalElements === 0 && 꿀조합의 첫번째 댓글을 달아보세요!} + 댓글 {totalElements}개 {comments.map((comment) => ( ))} diff --git a/src/components/Recipe/CommentList/commentList.css.ts b/src/components/Recipe/CommentList/commentList.css.ts new file mode 100644 index 000000000..9f250e070 --- /dev/null +++ b/src/components/Recipe/CommentList/commentList.css.ts @@ -0,0 +1,7 @@ +import { style } from '@vanilla-extract/css'; + +export const commentCount = style({ + color: '#808080', + fontSize: '1.2rem', + fontWeight: 500, +}); diff --git a/src/components/Recipe/RecipeFavoriteButton/RecipeFavoriteButton.tsx b/src/components/Recipe/RecipeFavoriteButton/RecipeFavoriteButton.tsx index 677848da5..d27ed0e72 100644 --- a/src/components/Recipe/RecipeFavoriteButton/RecipeFavoriteButton.tsx +++ b/src/components/Recipe/RecipeFavoriteButton/RecipeFavoriteButton.tsx @@ -1,4 +1,6 @@ -import { SvgIcon } from '@/components/Common'; +import { container } from './recipeFavoriteButton.css'; + +import { SvgIcon, Text } from '@/components/Common'; import { useTimeout } from '@/hooks/common'; import { useMemberQuery } from '@/hooks/queries/members'; import { useRecipeFavoriteMutation } from '@/hooks/queries/recipe'; @@ -9,7 +11,7 @@ interface RecipeFavoriteProps { favoriteCount?: number; } -const RecipeFavoriteButton = ({ recipeId, favorite }: RecipeFavoriteProps) => { +const RecipeFavoriteButton = ({ recipeId, favorite, favoriteCount }: RecipeFavoriteProps) => { const { mutate } = useRecipeFavoriteMutation(Number(recipeId)); const { data: member } = useMemberQuery(); @@ -20,7 +22,7 @@ const RecipeFavoriteButton = ({ recipeId, favorite }: RecipeFavoriteProps) => { const [debouncedToggleFavorite] = useTimeout(handleToggleFavorite, 200); return ( - <> + {member ? ( @@ -30,7 +32,10 @@ const RecipeFavoriteButton = ({ recipeId, favorite }: RecipeFavoriteProps) => { )} - > + + {favoriteCount} + + ); }; diff --git a/src/components/Recipe/RecipeFavoriteButton/recipeFavoriteButton.css.ts b/src/components/Recipe/RecipeFavoriteButton/recipeFavoriteButton.css.ts new file mode 100644 index 000000000..72d7e5fe7 --- /dev/null +++ b/src/components/Recipe/RecipeFavoriteButton/recipeFavoriteButton.css.ts @@ -0,0 +1,7 @@ +import { style } from '@vanilla-extract/css'; + +export const container = style({ + display: 'flex', + gap: 6, + alignItems: 'center', +}); diff --git a/src/mocks/data/recipeDetail.json b/src/mocks/data/recipeDetail.json index a8ba54c3d..8d17e8eee 100644 --- a/src/mocks/data/recipeDetail.json +++ b/src/mocks/data/recipeDetail.json @@ -9,14 +9,32 @@ }, "products": [ { - "id": 5, + "id": 1, + "image": "https://github.com/woowacourse-teams/2023-fun-eat/assets/78616893/1f0fd418-131c-4cf8-b540-112d762b7c34", "name": "불닭", - "price": 3000 + "price": 3000, + "averageRating": 4.5 }, { - "id": 5, + "id": 2, + "image": "https://github.com/woowacourse-teams/2023-fun-eat/assets/78616893/1f0fd418-131c-4cf8-b540-112d762b7c34", "name": "참치삼김", - "price": 4000 + "price": 4000, + "averageRating": 4.5 + }, + { + "id": 3, + "image": "https://github.com/woowacourse-teams/2023-fun-eat/assets/78616893/1f0fd418-131c-4cf8-b540-112d762b7c34", + "name": "바나나 우유", + "price": 1700, + "averageRating": 4.5 + }, + { + "id": 4, + "image": "https://github.com/woowacourse-teams/2023-fun-eat/assets/78616893/1f0fd418-131c-4cf8-b540-112d762b7c34", + "name": "하리보", + "price": 1200, + "averageRating": 4.3 } ], "totalPrice": 7000, diff --git a/src/pages/ProductSearchListPage/ProductSearchListPage.tsx b/src/pages/ProductSearchListPage/ProductSearchListPage.tsx index 7db784e5d..828710b08 100644 --- a/src/pages/ProductSearchListPage/ProductSearchListPage.tsx +++ b/src/pages/ProductSearchListPage/ProductSearchListPage.tsx @@ -26,7 +26,7 @@ export const ProductSearchListPage = () => { <> - + > diff --git a/src/pages/RecipeDetailPage.tsx b/src/pages/RecipeDetailPage.tsx deleted file mode 100644 index 1c21cc157..000000000 --- a/src/pages/RecipeDetailPage.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import { Divider, Heading, Spacing, Text, theme } from '@fun-eat/design-system'; -import { useQueryErrorResetBoundary } from '@tanstack/react-query'; -import { Suspense, useRef } from 'react'; -import { useParams } from 'react-router-dom'; -import styled from 'styled-components'; - -import RecipePreviewImage from '@/assets/plate.svg'; -import { ErrorBoundary, ErrorComponent, Loading, SectionTitle } from '@/components/Common'; -import { MemberImage } from '@/components/Members'; -import { CommentForm, CommentList, RecipeFavoriteButton } from '@/components/Recipe'; -import { useRecipeDetailQuery } from '@/hooks/queries/recipe'; -import { getFormattedDate } from '@/utils/date'; - -export const RecipeDetailPage = () => { - const { recipeId } = useParams(); - - const scrollTargetRef = useRef(null); - - const { data: recipeDetail } = useRecipeDetailQuery(Number(recipeId)); - const { reset } = useQueryErrorResetBoundary(); - - const { id, images, title, content, author, products, totalPrice, favorite, createdAt } = recipeDetail; - - return ( - <> - - - {images.length > 0 ? ( - - {images.map((image, index) => ( - - - - ))} - - ) : ( - - - - )} - - - - - - {author.nickname} 님 - {getFormattedDate(createdAt)} - - - - - - - - 🎁 어떤 상품을 사용했나요? - - - - {products.map(({ id, name, price }) => ( - - - {name} {price.toLocaleString('ko-KR')} 원 - - - ))} - - - 총 {totalPrice.toLocaleString('ko-KR')}원 - - - - - {content} - - - - - - }> - - - - - - - - - > - ); -}; - -const RecipeImageContainer = styled.ul` - display: flex; - flex-direction: column; - gap: 20px; - align-items: center; - - & > li { - width: 312px; - margin: 0 auto; - } -`; - -const RecipeImage = styled.img` - width: 100%; - height: auto; - border-radius: 10px; - object-fit: cover; -`; - -const RecipePreviewImageWrapper = styled.div` - display: flex; - justify-content: center; -`; - -const AuthorFavoriteWrapper = styled.div` - display: flex; - justify-content: space-between; - align-items: flex-end; -`; - -const AuthorWrapper = styled.div` - display: flex; - gap: 12px; - align-items: center; -`; - -const RecipeUsedProductsWrapper = styled.div` - padding: 20px; - border-radius: 8px; - background: ${({ theme }) => theme.backgroundColors.light}; -`; - -const RecipeContent = styled(Text)` - white-space: break-spaces; -`; diff --git a/src/pages/RecipeDetailPage/RecipeDetailPage.tsx b/src/pages/RecipeDetailPage/RecipeDetailPage.tsx new file mode 100644 index 000000000..7df2ae244 --- /dev/null +++ b/src/pages/RecipeDetailPage/RecipeDetailPage.tsx @@ -0,0 +1,123 @@ +import { BottomSheet, Spacing, useBottomSheet } from '@fun-eat/design-system'; +import { useQueryErrorResetBoundary } from '@tanstack/react-query'; +import { Suspense, useRef } from 'react'; +import { useParams } from 'react-router-dom'; + +import { + authorWrapper, + recipeImage, + recipeImageContainer, + container, + boxIcon, + recipeUsedProductsWrapper, + boxIconWrapper, + recipeUsedProductsImageList, + recipeContent, + productImageItem, + recipeProductsCount, + thirdProductImage, + bottomSheetWrapper, +} from './recipeDetailPage.css'; + +import { ErrorBoundary, ErrorComponent, Loading, SectionTitle, SvgIcon, Text } from '@/components/Common'; +import { MemberImage } from '@/components/Members'; +import { ProductOverviewList } from '@/components/Product'; +import { CommentForm, CommentList, RecipeFavoriteButton } from '@/components/Recipe'; +import { useRecipeDetailQuery } from '@/hooks/queries/recipe'; +import { vars } from '@/styles/theme.css'; +import { getFormattedDate } from '@/utils/date'; +import displaySlice from '@/utils/displaySlice'; + +export const RecipeDetailPage = () => { + const { recipeId } = useParams(); + + const scrollTargetRef = useRef(null); + + const { data: recipeDetail } = useRecipeDetailQuery(Number(recipeId)); + const { reset } = useQueryErrorResetBoundary(); + + const { isOpen, isClosing, handleOpenBottomSheet, handleCloseBottomSheet } = useBottomSheet(); + + const { id, images, title, content, author, products, favorite, favoriteCount, createdAt } = recipeDetail; + + return ( + <> + + + + + + + + {author.nickname} + + + {getFormattedDate(createdAt)} + + + + + {images.map((image, index) => ( + + + + ))} + + + + + + + + 이런 상품들을 사용했어요! + + + + {displaySlice(true, products, 3).map(({ id, name, image }, idx) => ( + + 3 && idx === 2 ? thirdProductImage : ''} + width={48} + height={48} + alt={name} + /> + {idx === 2 && ( + + +{products.length - 3} + + )} + + ))} + + + + + + + + + + + {content} + + + + + + + }> + + + + + + + + + + + + > + ); +}; diff --git a/src/pages/RecipeDetailPage/recipeDetailPage.css.ts b/src/pages/RecipeDetailPage/recipeDetailPage.css.ts new file mode 100644 index 000000000..61a35d62f --- /dev/null +++ b/src/pages/RecipeDetailPage/recipeDetailPage.css.ts @@ -0,0 +1,90 @@ +import { vars } from '@/styles/theme.css'; +import { style } from '@vanilla-extract/css'; + +export const flexRowContainer = style({ + display: 'flex', +}); + +export const flexColContainer = style({ + display: 'flex', + flexDirection: 'column', +}); + +export const container = style({ + padding: '0 20px', +}); + +export const authorWrapper = style({ + display: 'flex', + gap: 12, + alignItems: 'center', +}); + +export const recipeImageContainer = style([ + flexColContainer, + { + gap: 20, + alignItems: 'center', + }, +]); + +export const recipeImage = style({ + width: '100%', + height: 'auto', + objectFit: 'cover', +}); + +export const recipeUsedProductsWrapper = style({ + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', +}); + +export const boxIconWrapper = style({ + display: 'flex', + alignItems: 'center', +}); + +export const boxIcon = style({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: 26, + height: 26, + marginRight: 8, + background: vars.colors.gray5, + borderRadius: '50%', +}); + +export const recipeUsedProductsImageList = style({ + display: 'flex', + gap: 6, +}); + +export const productImageItem = style({ + position: 'relative', +}); + +export const thirdProductImage = style({ + filter: 'brightness(50%)', + borderRadius: 6, +}); + +export const recipeProductsCount = style({ + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate( -50%, -50% )', + color: vars.colors.white, +}); + +export const recipeContent = style({ + whiteSpace: 'break-spaces', +}); + +export const bottomSheetWrapper = style({ + display: 'flex', + flexDirection: 'column', + gap: 18, + padding: '54px 20px 20px 20px', +}); diff --git a/src/pages/ReviewDetailPage.tsx b/src/pages/ReviewDetailPage.tsx index 369706a01..3cf9d376b 100644 --- a/src/pages/ReviewDetailPage.tsx +++ b/src/pages/ReviewDetailPage.tsx @@ -4,7 +4,6 @@ import styled from 'styled-components'; import { SectionTitle, SvgIcon, TagList } from '@/components/Common'; import { MemberImage } from '@/components/Members'; -import { PATH } from '@/constants/path'; import { useReviewDetailQuery } from '@/hooks/queries/review'; import { getRelativeDate } from '@/utils/date'; @@ -31,7 +30,7 @@ export const ReviewDetailPage = () => { return ( - + diff --git a/src/router/index.tsx b/src/router/index.tsx index 61ab792da..b41bb8ba4 100644 --- a/src/router/index.tsx +++ b/src/router/index.tsx @@ -68,7 +68,7 @@ const router = createBrowserRouter([ path: `${PATH.RECIPE}/:recipeId`, async lazy() { const { RecipeDetailPage } = await import( - /* webpackChunkName: "RecipeDetailPage" */ '@/pages/RecipeDetailPage' + /* webpackChunkName: "RecipeDetailPage" */ '@/pages/RecipeDetailPage/RecipeDetailPage' ); return { Component: RecipeDetailPage }; }, diff --git a/src/styles/reset.css.ts b/src/styles/reset.css.ts index 532c6a996..dfbcb0146 100644 --- a/src/styles/reset.css.ts +++ b/src/styles/reset.css.ts @@ -6,6 +6,7 @@ globalStyle('#root', { height: '100vh', maxWidth: 400, margin: '0 auto', + lineHeight: 1.4, }); globalStyle('*::-webkit-scrollbar', { diff --git a/src/types/recipe.ts b/src/types/recipe.ts index 2d2a9bd9c..f8f843af3 100644 --- a/src/types/recipe.ts +++ b/src/types/recipe.ts @@ -14,6 +14,7 @@ export interface RecipeDetail extends Recipe { content: string; totalPrice: number; favorite: boolean; + favoriteCount: number; } export interface Recipe {
댓글 {totalElements}개