From 752622d996e1159214096580f96f97c474472b74 Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Wed, 17 Apr 2024 23:13:33 +0200 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=EC=97=90=EC=84=9C=20=EC=84=B8=EC=85=98=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EB=94=94=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/queries/product/useInfiniteProductReviewsQuery.ts | 1 - src/mocks/handlers/reviewHandlers.ts | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/hooks/queries/product/useInfiniteProductReviewsQuery.ts b/src/hooks/queries/product/useInfiniteProductReviewsQuery.ts index 8142c77e0..8f7789940 100644 --- a/src/hooks/queries/product/useInfiniteProductReviewsQuery.ts +++ b/src/hooks/queries/product/useInfiniteProductReviewsQuery.ts @@ -7,7 +7,6 @@ const fetchProductReviews = async (pageParam: number, productId: number, sort: s const res = await productApi.get({ params: `/${productId}/reviews`, queries: `?sort=${sort}&lastReviewId=${pageParam}`, - credentials: true, }); const data: ProductReviewResponse = await res.json(); diff --git a/src/mocks/handlers/reviewHandlers.ts b/src/mocks/handlers/reviewHandlers.ts index 656891e55..5aef00fb7 100644 --- a/src/mocks/handlers/reviewHandlers.ts +++ b/src/mocks/handlers/reviewHandlers.ts @@ -10,13 +10,8 @@ import type { ReviewFavoriteRequestBody } from '@/types/review'; export const reviewHandlers = [ rest.get('/api/products/:productId/reviews', (req, res, ctx) => { - const { mockSessionId } = req.cookies; const sortOptions = req.url.searchParams.get('sort'); - if (!mockSessionId) { - return res(ctx.status(401)); - } - if (sortOptions === null) { return res(ctx.status(400)); } From 304f0ae5afb76249976e178f918e30dd5f8ebdf3 Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Wed, 17 Apr 2024 23:19:14 +0200 Subject: [PATCH 02/11] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=8F=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=A7=81=ED=81=AC=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProductDetailPage/ProductDetailPage.tsx | 19 ++++++++++++------- .../productDetailPage.css.ts | 14 ++++++-------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/pages/ProductDetailPage/ProductDetailPage.tsx b/src/pages/ProductDetailPage/ProductDetailPage.tsx index 0367084c3..9739a4701 100644 --- a/src/pages/ProductDetailPage/ProductDetailPage.tsx +++ b/src/pages/ProductDetailPage/ProductDetailPage.tsx @@ -1,9 +1,9 @@ import { BottomSheet, useBottomSheet } from '@fun-eat/design-system'; import { useQueryErrorResetBoundary } from '@tanstack/react-query'; import { Suspense } from 'react'; -import { useParams, useLocation, useNavigate } from 'react-router-dom'; +import { useParams, useLocation, useNavigate, Link } from 'react-router-dom'; -import { main, registerButton, registerButtonWrapper, section, sortWrapper } from './productDetailPage.css'; +import { link, linkWrapper, main, section, sortWrapper } from './productDetailPage.css'; import NotFoundPage from '../NotFoundPage'; import { @@ -86,11 +86,16 @@ export const ProductDetailPage = () => { - {/*로그인 여부에 따라 링크 경로*/} -
- +
+ {member ? ( + + 리뷰 작성하기 + + ) : ( + + )}
diff --git a/src/pages/ProductDetailPage/productDetailPage.css.ts b/src/pages/ProductDetailPage/productDetailPage.css.ts index 78cc32f30..7e8701b79 100644 --- a/src/pages/ProductDetailPage/productDetailPage.css.ts +++ b/src/pages/ProductDetailPage/productDetailPage.css.ts @@ -1,5 +1,5 @@ import { vars } from '@/styles/theme.css'; -import { style, styleVariants } from '@vanilla-extract/css'; +import { style } from '@vanilla-extract/css'; export const main = style({ paddingBottom: 70, @@ -16,7 +16,7 @@ export const sortWrapper = style({ right: 20, }); -export const registerButtonWrapper = style({ +export const linkWrapper = style({ position: 'fixed', left: '50%', bottom: 0, @@ -32,7 +32,10 @@ export const registerButtonWrapper = style({ transform: 'translateX(-50%)', }); -const registerButtonBase = style({ +export const link = style({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', width: '100%', height: 56, backgroundColor: vars.colors.primary, @@ -40,8 +43,3 @@ const registerButtonBase = style({ borderRadius: 6, fontWeight: 700, }); - -export const registerButton = styleVariants({ - active: [registerButtonBase, { backgroundColor: vars.colors.primary }], - disabled: [registerButtonBase, { backgroundColor: vars.colors.background.tag }], -}); From dd66dde7eedc125d01a4fed0fd2dbb40827cd38e Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Thu, 18 Apr 2024 00:01:56 +0200 Subject: [PATCH 03/11] =?UTF-8?q?feat:=20=ED=83=91=EB=B0=94=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EB=B2=84=ED=8A=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Common/TopBar/TopBar.tsx | 16 +++++++++------- src/components/Common/TopBar/topBar.css.ts | 8 ++++++++ src/components/Common/index.ts | 1 + 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/components/Common/TopBar/TopBar.tsx b/src/components/Common/TopBar/TopBar.tsx index 5197fa3b0..a9ba61ddc 100644 --- a/src/components/Common/TopBar/TopBar.tsx +++ b/src/components/Common/TopBar/TopBar.tsx @@ -1,6 +1,7 @@ +import type { ComponentPropsWithoutRef } from 'react'; import { Link } from 'react-router-dom'; -import { LeftNavigationWrapper, container, headerTitle, leftTitle } from './topBar.css'; +import { LeftNavigationWrapper, container, headerTitle, leftTitle, register } from './topBar.css'; import SvgIcon from '../Svg/SvgIcon'; import Text from '../Text/Text'; @@ -8,7 +9,6 @@ import LogoImage from '@/assets/logo.svg'; import { PATH } from '@/constants/path'; import { vars } from '@/styles/theme.css'; - interface TopBarProps { children?: React.ReactNode; title?: string; @@ -16,6 +16,8 @@ interface TopBarProps { state?: unknown; } +type RegisterButtonProps = ComponentPropsWithoutRef<'button'>; + const TopBar = ({ children }: TopBarProps) => { return
{children}
; }; @@ -58,13 +60,13 @@ const SearchLink = () => { ); }; -const RegisterLink = ({ link = '' }: TopBarProps) => { +const RegisterButton = ({ ...props }: RegisterButtonProps) => { return ( - - + ); }; @@ -85,7 +87,7 @@ TopBar.BackLink = BackLink; TopBar.LeftNavigationGroup = LeftNavigationGroup; TopBar.Title = Title; TopBar.SearchLink = SearchLink; -TopBar.RegisterLink = RegisterLink; +TopBar.RegisterButton = RegisterButton; TopBar.CloseButton = CloseButton; TopBar.Spacer = Spacer; diff --git a/src/components/Common/TopBar/topBar.css.ts b/src/components/Common/TopBar/topBar.css.ts index fcca96df1..4101c69b4 100644 --- a/src/components/Common/TopBar/topBar.css.ts +++ b/src/components/Common/TopBar/topBar.css.ts @@ -34,3 +34,11 @@ export const headerTitle = style({ fontSize: 18, fontWeight: 600, }); + +export const register = style({ + selectors: { + 'button:disabled > &': { + color: vars.colors.text.disabled, + }, + }, +}); diff --git a/src/components/Common/index.ts b/src/components/Common/index.ts index ef1d5042d..7e440353c 100644 --- a/src/components/Common/index.ts +++ b/src/components/Common/index.ts @@ -25,3 +25,4 @@ export { default as PageHeader } from './PageHeader/PageHeader'; export { default as Badge } from './Badge/Badge'; export { default as WriteButton } from './WriteButton/WriteButton'; export { default as Text } from './Text/Text'; +export { default as TopBar } from './TopBar/TopBar'; From e339f3763923d2d69dbe8dbadce0c04258a5a1f3 Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Thu, 18 Apr 2024 00:02:57 +0200 Subject: [PATCH 04/11] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=ED=8F=BC=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80?= =?UTF-8?q?=EC=82=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReviewRegisterForm/ReviewRegisterForm.tsx | 21 ++++--------- .../Review/ReviewTagList/ReviewTagList.tsx | 4 ++- .../Review/ReviewTagSheet/ReviewTagSheet.tsx | 4 ++- src/contexts/ReviewFormContext.tsx | 23 +++++++++----- .../ReviewRegisterPage/ReviewRegisterPage.tsx | 14 +++++++-- .../reviewRegisterPage.css.ts | 2 +- src/router/index.tsx | 30 +++++++++++++------ 7 files changed, 61 insertions(+), 37 deletions(-) diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx index dbbc04559..bfb913e47 100644 --- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx +++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx @@ -8,7 +8,6 @@ import StarRate from './StarRate/StarRate'; import RebuyCheckbox from '../RebuyCheckbox/RebuyCheckbox'; import { ImageUploader, SvgIcon, Text } from '@/components/Common'; -import { MAX_DISPLAYED_TAGS_LENGTH, MIN_DISPLAYED_TAGS_LENGTH } from '@/constants'; import type { TagValue } from '@/contexts/ReviewFormContext'; import { useFormData, useImageUploader } from '@/hooks/common'; import { useReviewFormActionContext, useReviewFormValueContext } from '@/hooks/context'; @@ -16,31 +15,21 @@ import { useReviewRegisterFormMutation } from '@/hooks/queries/review'; import { vars } from '@/styles/theme.css'; import type { ReviewRequest } from '@/types/review'; -const MIN_RATING_SCORE = 0; -const MIN_CONTENT_LENGTH = 0; - interface ReviewRegisterFormProps { productId: number; openBottomSheet: () => void; } const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormProps) => { - const { isImageUploading, previewImage, imageFile, uploadImage, deleteImage } = useImageUploader(); + const { previewImage, imageFile, uploadImage, deleteImage } = useImageUploader(); const navigate = useNavigate(); - const reviewFormValue = useReviewFormValueContext(); + const { reviewFormValue } = useReviewFormValueContext(); const { handleReviewFormValue, resetReviewFormValue } = useReviewFormActionContext(); const { toast } = useToastActionContext(); const { mutate } = useReviewRegisterFormMutation(productId); - const isValid = - reviewFormValue.rating > MIN_RATING_SCORE && - reviewFormValue.tags.length >= MIN_DISPLAYED_TAGS_LENGTH && - reviewFormValue.tags.length <= MAX_DISPLAYED_TAGS_LENGTH && - reviewFormValue.content.length > MIN_CONTENT_LENGTH && - !isImageUploading; - const formValue: ReviewRequest = { ...reviewFormValue, tagIds: reviewFormValue.tags.map(({ id }) => id) }; const formData = useFormData({ @@ -81,7 +70,7 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr }; return ( -
+

사진 등록 @@ -105,7 +94,9 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr {reviewFormValue.tags.map((tag) => (
  • diff --git a/src/components/Review/ReviewTagList/ReviewTagList.tsx b/src/components/Review/ReviewTagList/ReviewTagList.tsx index 46363462d..dbbc36df8 100644 --- a/src/components/Review/ReviewTagList/ReviewTagList.tsx +++ b/src/components/Review/ReviewTagList/ReviewTagList.tsx @@ -10,7 +10,9 @@ import { useReviewTagsQuery } from '@/hooks/queries/review'; const ReviewTagList = () => { const { data: tagsData } = useReviewTagsQuery(); - const { tags: selectedTags } = useReviewFormValueContext(); + const { + reviewFormValue: { tags: selectedTags }, + } = useReviewFormValueContext(); const { handleReviewFormValue } = useReviewFormActionContext(); const isChecked = (tag: TagValue) => selectedTags.some(({ id }) => id === tag.id); diff --git a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx index 10d5b0d81..14ee56da4 100644 --- a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx +++ b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx @@ -9,7 +9,9 @@ interface ReviewTagSheetProps { } const ReviewTagSheet = ({ close }: ReviewTagSheetProps) => { - const { tags } = useReviewFormValueContext(); + const { + reviewFormValue: { tags }, + } = useReviewFormValueContext(); const isValid = tags.length >= MIN_DISPLAYED_TAGS_LENGTH && tags.length <= MAX_DISPLAYED_TAGS_LENGTH; diff --git a/src/contexts/ReviewFormContext.tsx b/src/contexts/ReviewFormContext.tsx index 0cc00f281..a534ab8b0 100644 --- a/src/contexts/ReviewFormContext.tsx +++ b/src/contexts/ReviewFormContext.tsx @@ -2,7 +2,7 @@ import { useToastActionContext } from '@fun-eat/design-system'; import type { PropsWithChildren } from 'react'; import { createContext, useState } from 'react'; -import { MAX_DISPLAYED_TAGS_LENGTH } from '@/constants'; +import { MAX_DISPLAYED_TAGS_LENGTH, MIN_DISPLAYED_TAGS_LENGTH } from '@/constants'; import type { ReviewRequest } from '@/types/review'; export interface TagValue { @@ -18,6 +18,11 @@ interface ReviewFormActionParams { value: ReviewFormValues; } +interface Value { + isValid: boolean; + reviewFormValue: ReviewFormValue; +} + interface ReviewFormAction { handleReviewFormValue: (params: ReviewFormActionParams) => void; resetReviewFormValue: () => void; @@ -31,14 +36,13 @@ const initialReviewFormValue: ReviewFormValue = { }; const MIN_RATING_SCORE = 0; -const MIN_SELECTED_TAGS_COUNT = 1; -const MIN_CONTENT_LENGTH = 0; +const MIN_CONTENT_LENGTH = 10; const isTagValue = (value: ReviewFormValues): value is TagValue => typeof value === 'object' && 'id' in value && 'name' in value; const isSelectedTag = (tags: TagValue[], selectedTag: TagValue) => tags.some(({ id }) => id === selectedTag.id); -export const ReviewFormValueContext = createContext(null); +export const ReviewFormValueContext = createContext(null); export const ReviewFormActionContext = createContext(null); const ReviewFormProvider = ({ children }: PropsWithChildren) => { @@ -47,9 +51,9 @@ const ReviewFormProvider = ({ children }: PropsWithChildren) => { const isValid = reviewFormValue.rating > MIN_RATING_SCORE && - reviewFormValue.tags.length >= MIN_SELECTED_TAGS_COUNT && + reviewFormValue.tags.length >= MIN_DISPLAYED_TAGS_LENGTH && reviewFormValue.tags.length <= MAX_DISPLAYED_TAGS_LENGTH && - reviewFormValue.content.length > MIN_CONTENT_LENGTH; + reviewFormValue.content.length >= MIN_CONTENT_LENGTH; const handleReviewFormValue = ({ target, value }: ReviewFormActionParams) => { setReviewFormValue((prev) => { @@ -76,6 +80,11 @@ const ReviewFormProvider = ({ children }: PropsWithChildren) => { setReviewFormValue(initialReviewFormValue); }; + const value = { + isValid, + reviewFormValue, + }; + const reviewFormAction = { handleReviewFormValue, resetReviewFormValue, @@ -83,7 +92,7 @@ const ReviewFormProvider = ({ children }: PropsWithChildren) => { return ( - {children} + {children} ); }; diff --git a/src/pages/ReviewRegisterPage/ReviewRegisterPage.tsx b/src/pages/ReviewRegisterPage/ReviewRegisterPage.tsx index 06ca594d8..5b2802551 100644 --- a/src/pages/ReviewRegisterPage/ReviewRegisterPage.tsx +++ b/src/pages/ReviewRegisterPage/ReviewRegisterPage.tsx @@ -4,19 +4,27 @@ import { useParams } from 'react-router-dom'; import { section } from './reviewRegisterPage.css'; import NotFoundPage from '../NotFoundPage'; +import { TopBar } from '@/components/Common'; import { ReviewRegisterForm, ReviewTagSheet } from '@/components/Review'; -import ReviewFormProvider from '@/contexts/ReviewFormContext'; +import { useReviewFormValueContext } from '@/hooks/context'; export const ReviewRegisterPage = () => { const { productId } = useParams<{ productId: string }>(); + const { isValid } = useReviewFormValueContext(); const { isOpen, isClosing, handleOpenBottomSheet, handleCloseBottomSheet } = useBottomSheet(); if (!productId || isNaN(Number(productId))) { return ; } + console.log(isValid); + return ( - + <> + + + +
    @@ -25,6 +33,6 @@ export const ReviewRegisterPage = () => {
    -
    + ); }; diff --git a/src/pages/ReviewRegisterPage/reviewRegisterPage.css.ts b/src/pages/ReviewRegisterPage/reviewRegisterPage.css.ts index 93a5f54f2..408efe7b5 100644 --- a/src/pages/ReviewRegisterPage/reviewRegisterPage.css.ts +++ b/src/pages/ReviewRegisterPage/reviewRegisterPage.css.ts @@ -2,5 +2,5 @@ import { style } from '@vanilla-extract/css'; export const section = style({ padding: '0 20px', - marginBottom: 32, + margin: '16px 0 32px', }); diff --git a/src/router/index.tsx b/src/router/index.tsx index 8f0e1be10..b51d23364 100644 --- a/src/router/index.tsx +++ b/src/router/index.tsx @@ -5,6 +5,7 @@ import App from './App'; import { AuthLayout } from '@/components/Layout'; import { PATH } from '@/constants/path'; import CategoryProvider from '@/contexts/CategoryContext'; +import ReviewFormProvider from '@/contexts/ReviewFormContext'; import NotFoundPage from '@/pages/NotFoundPage'; const router = createBrowserRouter([ @@ -179,15 +180,6 @@ const router = createBrowserRouter([ return { Component: ProductDetailPage }; }, }, - { - path: `${PATH.PRODUCT_LIST}/detail/:productId/review-register`, - async lazy() { - const { ReviewRegisterPage } = await import( - /* webpackChunkName: "ReviewRegisterPage" */ '@/pages/ReviewRegisterPage/ReviewRegisterPage' - ); - return { Component: ReviewRegisterPage }; - }, - }, { path: PATH.SEARCH, async lazy() { @@ -215,6 +207,26 @@ const router = createBrowserRouter([ }, ], }, + { + path: '/', + element: ( + + + + ), + errorElement: , + children: [ + { + path: `${PATH.PRODUCT_LIST}/detail/:productId/review-register`, + async lazy() { + const { ReviewRegisterPage } = await import( + /* webpackChunkName: "ReviewRegisterPage" */ '@/pages/ReviewRegisterPage/ReviewRegisterPage' + ); + return { Component: ReviewRegisterPage }; + }, + }, + ], + }, ]); export default router; From e20d1da71771e2b0d0d988194d4abf1fc34923ed Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Thu, 18 Apr 2024 00:03:14 +0200 Subject: [PATCH 05/11] =?UTF-8?q?feat:=20=ED=83=9C=EA=B7=B8=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Review/ReviewRegisterForm/reviewRegisterForm.css.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts index f9e43fc24..d947c84f4 100644 --- a/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts +++ b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts @@ -37,8 +37,6 @@ export const tagButton = style({ gap: 4, height: 28, padding: '0 6px', - fontSize: '1.3rem', - fontWeight: 500, borderRadius: 4, backgroundColor: vars.colors.gray2, }); From 2eb6a2d21d206cc96a9b4bb392cd529bb76df7b0 Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Thu, 18 Apr 2024 00:10:20 +0200 Subject: [PATCH 06/11] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=ED=83=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=84=A0=ED=83=9D=20=EB=B0=94=ED=85=80=EC=8B=9C?= =?UTF-8?q?=ED=8A=B8=20=EB=8B=AB=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Review/ReviewTagSheet/ReviewTagSheet.tsx | 9 ++++++++- .../Review/ReviewTagSheet/reviewTagSheet.css.ts | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx index 14ee56da4..21c650f10 100644 --- a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx +++ b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx @@ -1,8 +1,10 @@ -import { container, registerButton, registerButtonWrapper, section } from './reviewTagSheet.css'; +import { closeWrapper, container, registerButton, registerButtonWrapper, section } from './reviewTagSheet.css'; import ReviewTagList from '../ReviewTagList/ReviewTagList'; +import { SvgIcon } from '@/components/Common'; import { MAX_DISPLAYED_TAGS_LENGTH, MIN_DISPLAYED_TAGS_LENGTH } from '@/constants'; import { useReviewFormValueContext } from '@/hooks/context'; +import { vars } from '@/styles/theme.css'; interface ReviewTagSheetProps { close: () => void; @@ -17,6 +19,11 @@ const ReviewTagSheet = ({ close }: ReviewTagSheetProps) => { return (
    +
    + +
    diff --git a/src/components/Review/ReviewTagSheet/reviewTagSheet.css.ts b/src/components/Review/ReviewTagSheet/reviewTagSheet.css.ts index 8d689d3e7..c069c38cf 100644 --- a/src/components/Review/ReviewTagSheet/reviewTagSheet.css.ts +++ b/src/components/Review/ReviewTagSheet/reviewTagSheet.css.ts @@ -5,9 +5,17 @@ export const container = style({ height: '100vh', }); +export const closeWrapper = style({ + padding: '0 20px', + display: 'flex', + height: 50, + alignItems: 'center', + justifyContent: 'flex-end', +}); + export const section = style({ - padding: '50px 20px 70px', - marginBottom: 32, + padding: '0 20px', + margin: '16px 0 32px', }); export const registerButtonWrapper = style({ From cca14974b2923b3d228ae36d21f19ae827089fa2 Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Thu, 18 Apr 2024 00:13:33 +0200 Subject: [PATCH 07/11] =?UTF-8?q?feat:=20=EA=BF=80=EC=A1=B0=ED=95=A9=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EB=B3=B4=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Product/ProductRecipeList/ProductRecipeList.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/Product/ProductRecipeList/ProductRecipeList.tsx b/src/components/Product/ProductRecipeList/ProductRecipeList.tsx index 6a943c664..e81c8a88f 100644 --- a/src/components/Product/ProductRecipeList/ProductRecipeList.tsx +++ b/src/components/Product/ProductRecipeList/ProductRecipeList.tsx @@ -35,7 +35,14 @@ const ProductRecipeList = ({ productId }: ProductRecipeListProps) => { {/*링크는 상품이 포함된 꿀조합 검색결과로 가는 것이 맞을듯?*/}
    - +
    전체보기 From 7e2eb672e3a28637ffec1ab97dd289d611f09d52 Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Thu, 18 Apr 2024 00:24:04 +0200 Subject: [PATCH 08/11] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EA=BF=80=EC=A1=B0=ED=95=A9=20=EC=97=86=EC=9D=84?= =?UTF-8?q?=EC=8B=9C=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProductRecipeList/ProductRecipeList.tsx | 27 +++++++++++++++++-- .../productRecipeList.css.ts | 18 +++++++++++++ .../Search/SearchNotFound/SearchNotFound.tsx | 23 +++++++--------- 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/components/Product/ProductRecipeList/ProductRecipeList.tsx b/src/components/Product/ProductRecipeList/ProductRecipeList.tsx index e81c8a88f..3b41cbf6c 100644 --- a/src/components/Product/ProductRecipeList/ProductRecipeList.tsx +++ b/src/components/Product/ProductRecipeList/ProductRecipeList.tsx @@ -1,9 +1,19 @@ import { Link } from 'react-router-dom'; -import { container, moreIcon, moreIconWrapper, moreItem, moreLink } from './productRecipeList.css'; +import { + container, + moreIcon, + moreIconWrapper, + moreItem, + moreLink, + notFound, + recipeLink, +} from './productRecipeList.css'; +import SearchNotFoundImage from '@/assets/search-notfound.png'; import { SvgIcon, Text } from '@/components/Common'; import { RecipeItem } from '@/components/Recipe'; +import { PATH } from '@/constants/path'; import { useInfiniteProductRecipesQuery } from '@/hooks/queries/product'; import { vars } from '@/styles/theme.css'; import displaySlice from '@/utils/displaySlice'; @@ -20,7 +30,20 @@ const ProductRecipeList = ({ productId }: ProductRecipeListProps) => { const recipeToDisplay = displaySlice(true, recipes, 3); if (recipes.length === 0) { - return null; + return ( +
    + 검색 결과 없음 + + 아직 작성된 꿀조합이 없어요 + +
    + + + 꿀조합 작성하러 가기 + + +
    + ); } return ( diff --git a/src/components/Product/ProductRecipeList/productRecipeList.css.ts b/src/components/Product/ProductRecipeList/productRecipeList.css.ts index 5c7824bab..524345d3a 100644 --- a/src/components/Product/ProductRecipeList/productRecipeList.css.ts +++ b/src/components/Product/ProductRecipeList/productRecipeList.css.ts @@ -36,3 +36,21 @@ export const moreIconWrapper = style({ export const moreIcon = style({ transform: 'rotate(180deg)', }); + +export const notFound = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: 6, + textAlign: 'center', +}); + +export const recipeLink = style({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: 34, + padding: '0 16px', + backgroundColor: vars.colors.gray2, + borderRadius: 44, +}); diff --git a/src/components/Search/SearchNotFound/SearchNotFound.tsx b/src/components/Search/SearchNotFound/SearchNotFound.tsx index 764f3d969..f1c1479ae 100644 --- a/src/components/Search/SearchNotFound/SearchNotFound.tsx +++ b/src/components/Search/SearchNotFound/SearchNotFound.tsx @@ -3,21 +3,18 @@ import { container } from './searchNotFound.css'; import SearchNotFoundImage from '@/assets/search-notfound.png'; import { Text } from '@/components/Common'; - const SearchNotFound = () => { return ( - <> -
    - 검색 결과 없음 - - 검색 결과가 없어요 - -
    - - 다른 키워드로 검색해보세요! - -
    - +
    + 검색 결과 없음 + + 검색 결과가 없어요 + +
    + + 다른 키워드로 검색해보세요! + +
    ); }; From c7d7c548a490cab27fb4ac06ca7f664980d77eb2 Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Thu, 18 Apr 2024 00:28:47 +0200 Subject: [PATCH 09/11] =?UTF-8?q?refactor:=20=EC=BD=98=EC=86=94=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ReviewRegisterPage/ReviewRegisterPage.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/ReviewRegisterPage/ReviewRegisterPage.tsx b/src/pages/ReviewRegisterPage/ReviewRegisterPage.tsx index 5b2802551..b9251483a 100644 --- a/src/pages/ReviewRegisterPage/ReviewRegisterPage.tsx +++ b/src/pages/ReviewRegisterPage/ReviewRegisterPage.tsx @@ -17,8 +17,6 @@ export const ReviewRegisterPage = () => { return ; } - console.log(isValid); - return ( <> From 0060bf4ce435046653ac86bc0581c25ee92e0339 Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Thu, 18 Apr 2024 00:53:53 +0200 Subject: [PATCH 10/11] =?UTF-8?q?fix:=20=EC=8A=A4=ED=86=A0=EB=A6=AC?= =?UTF-8?q?=EB=B6=81=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Common/TopBar/TopBar.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Common/TopBar/TopBar.stories.tsx b/src/components/Common/TopBar/TopBar.stories.tsx index 93b27658d..c67c30c86 100644 --- a/src/components/Common/TopBar/TopBar.stories.tsx +++ b/src/components/Common/TopBar/TopBar.stories.tsx @@ -71,7 +71,7 @@ export const LeftTitleAndRegister: Story = { return ( - + ); }, From bb22d724e2eafb4051655d509fc40b90622545a6 Mon Sep 17 00:00:00 2001 From: Leejin-Yang Date: Fri, 19 Apr 2024 21:00:57 +0200 Subject: [PATCH 11/11] =?UTF-8?q?style:=20=EB=A6=AC=EB=B7=B0=20=ED=8F=BC?= =?UTF-8?q?=20=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReviewRegisterForm/ReviewRegisterForm.tsx | 2 +- .../Review/ReviewTagList/ReviewTagList.tsx | 2 +- .../Review/ReviewTagSheet/ReviewTagSheet.tsx | 2 +- src/contexts/ReviewFormContext.tsx | 34 +++++++++---------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx index bfb913e47..99d0dd85c 100644 --- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx +++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx @@ -24,7 +24,7 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr const { previewImage, imageFile, uploadImage, deleteImage } = useImageUploader(); const navigate = useNavigate(); - const { reviewFormValue } = useReviewFormValueContext(); + const { formValue: reviewFormValue } = useReviewFormValueContext(); const { handleReviewFormValue, resetReviewFormValue } = useReviewFormActionContext(); const { toast } = useToastActionContext(); diff --git a/src/components/Review/ReviewTagList/ReviewTagList.tsx b/src/components/Review/ReviewTagList/ReviewTagList.tsx index dbbc36df8..126adb76e 100644 --- a/src/components/Review/ReviewTagList/ReviewTagList.tsx +++ b/src/components/Review/ReviewTagList/ReviewTagList.tsx @@ -11,7 +11,7 @@ import { useReviewTagsQuery } from '@/hooks/queries/review'; const ReviewTagList = () => { const { data: tagsData } = useReviewTagsQuery(); const { - reviewFormValue: { tags: selectedTags }, + formValue: { tags: selectedTags }, } = useReviewFormValueContext(); const { handleReviewFormValue } = useReviewFormActionContext(); diff --git a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx index 21c650f10..3364f52ac 100644 --- a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx +++ b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx @@ -12,7 +12,7 @@ interface ReviewTagSheetProps { const ReviewTagSheet = ({ close }: ReviewTagSheetProps) => { const { - reviewFormValue: { tags }, + formValue: { tags }, } = useReviewFormValueContext(); const isValid = tags.length >= MIN_DISPLAYED_TAGS_LENGTH && tags.length <= MAX_DISPLAYED_TAGS_LENGTH; diff --git a/src/contexts/ReviewFormContext.tsx b/src/contexts/ReviewFormContext.tsx index a534ab8b0..65e2f18ca 100644 --- a/src/contexts/ReviewFormContext.tsx +++ b/src/contexts/ReviewFormContext.tsx @@ -10,17 +10,17 @@ export interface TagValue { name: string; } -type ReviewFormValue = Omit & { tags: TagValue[] }; -type ReviewFormValues = Exclude | TagValue; +type FormValue = Omit & { tags: TagValue[] }; +type FormValues = Exclude | TagValue; interface ReviewFormActionParams { - target: keyof ReviewFormValue; - value: ReviewFormValues; + target: keyof FormValue; + value: FormValues; } -interface Value { +interface ReviewFormValue { isValid: boolean; - reviewFormValue: ReviewFormValue; + formValue: FormValue; } interface ReviewFormAction { @@ -28,7 +28,7 @@ interface ReviewFormAction { resetReviewFormValue: () => void; } -const initialReviewFormValue: ReviewFormValue = { +const initialFormValue: FormValue = { rating: 0, tags: [], content: '', @@ -38,25 +38,25 @@ const initialReviewFormValue: ReviewFormValue = { const MIN_RATING_SCORE = 0; const MIN_CONTENT_LENGTH = 10; -const isTagValue = (value: ReviewFormValues): value is TagValue => +const isTagValue = (value: FormValues): value is TagValue => typeof value === 'object' && 'id' in value && 'name' in value; const isSelectedTag = (tags: TagValue[], selectedTag: TagValue) => tags.some(({ id }) => id === selectedTag.id); -export const ReviewFormValueContext = createContext(null); +export const ReviewFormValueContext = createContext(null); export const ReviewFormActionContext = createContext(null); const ReviewFormProvider = ({ children }: PropsWithChildren) => { - const [reviewFormValue, setReviewFormValue] = useState(initialReviewFormValue); + const [formValue, setFormValue] = useState(initialFormValue); const { toast } = useToastActionContext(); const isValid = - reviewFormValue.rating > MIN_RATING_SCORE && - reviewFormValue.tags.length >= MIN_DISPLAYED_TAGS_LENGTH && - reviewFormValue.tags.length <= MAX_DISPLAYED_TAGS_LENGTH && - reviewFormValue.content.length >= MIN_CONTENT_LENGTH; + formValue.rating > MIN_RATING_SCORE && + formValue.tags.length >= MIN_DISPLAYED_TAGS_LENGTH && + formValue.tags.length <= MAX_DISPLAYED_TAGS_LENGTH && + formValue.content.length >= MIN_CONTENT_LENGTH; const handleReviewFormValue = ({ target, value }: ReviewFormActionParams) => { - setReviewFormValue((prev) => { + setFormValue((prev) => { const targetValue = prev[target]; if (isTagValue(value) && Array.isArray(targetValue)) { @@ -77,12 +77,12 @@ const ReviewFormProvider = ({ children }: PropsWithChildren) => { }; const resetReviewFormValue = () => { - setReviewFormValue(initialReviewFormValue); + setFormValue(initialFormValue); }; const value = { isValid, - reviewFormValue, + formValue, }; const reviewFormAction = {