From e3ce36603172a2a5f82beacca36dd5b0b6e2111a Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sat, 6 Apr 2024 18:48:20 +0200
Subject: [PATCH 01/27] =?UTF-8?q?feat:=20=EC=82=AC=EC=A7=84=20=EC=95=84?=
=?UTF-8?q?=EC=9D=B4=EC=BD=98=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.storybook/preview-body.html | 5 +++++
src/components/Common/Svg/SvgIcon.tsx | 1 +
src/components/Common/Svg/SvgSprite.tsx | 3 +++
3 files changed, 9 insertions(+)
diff --git a/.storybook/preview-body.html b/.storybook/preview-body.html
index 0e19cf71..75390831 100644
--- a/.storybook/preview-body.html
+++ b/.storybook/preview-body.html
@@ -128,6 +128,11 @@
d="M20.2 4.683a1.013 1.013 0 0 1 0 1.438L9.008 17.317a1.013 1.013 0 0 1-1.437 0L1.8 11.55a1.017 1.017 0 0 1 1.437-1.437l5.045 5.045L18.758 4.683a1.013 1.013 0 0 1 1.437 0h.005z"
/>
+
+
+
{
+
+
+
From 3ed017325f98c3d85c90ed9f90447635ed2e9207 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sat, 6 Apr 2024 18:55:09 +0200
Subject: [PATCH 02/27] =?UTF-8?q?feat:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?=
=?UTF-8?q?=EC=97=85=EB=A1=9C=EB=8D=94=20=EA=B0=9C=ED=8E=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Common/ImageUploader/ImageUploader.tsx | 29 +++-----
.../Common/ImageUploader/imageUploader.css.ts | 17 +++++
.../ReviewRegisterForm/ReviewRegisterForm.tsx | 69 +++++++------------
.../reviewRegisterForm.css.ts | 7 ++
4 files changed, 56 insertions(+), 66 deletions(-)
create mode 100644 src/components/Common/ImageUploader/imageUploader.css.ts
create mode 100644 src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
diff --git a/src/components/Common/ImageUploader/ImageUploader.tsx b/src/components/Common/ImageUploader/ImageUploader.tsx
index b139a1b4..6202d0e9 100644
--- a/src/components/Common/ImageUploader/ImageUploader.tsx
+++ b/src/components/Common/ImageUploader/ImageUploader.tsx
@@ -2,8 +2,12 @@ import { Button, useToastActionContext } from '@fun-eat/design-system';
import type { ChangeEventHandler } from 'react';
import styled from 'styled-components';
+import { uploadInput, uploadLabel } from './imageUploader.css';
+import SvgIcon from '../Svg/SvgIcon';
+
import { IMAGE_MAX_SIZE } from '@/constants';
import { useEnterKeyDown } from '@/hooks/common';
+import { vars } from '@/styles/theme.css';
interface ReviewImageUploaderProps {
previewImage: string;
@@ -33,6 +37,7 @@ const ImageUploader = ({ previewImage, uploadImage, deleteImage }: ReviewImageUp
return (
<>
+ {/*이미지 미리보기 디자인*/}
{previewImage ? (
@@ -41,10 +46,10 @@ const ImageUploader = ({ previewImage, uploadImage, deleteImage }: ReviewImageUp
) : (
-
- +
-
-
+
)}
>
);
@@ -52,22 +57,6 @@ const ImageUploader = ({ previewImage, uploadImage, deleteImage }: ReviewImageUp
export default ImageUploader;
-const ImageUploadLabel = styled.label`
- display: flex;
- justify-content: center;
- align-items: center;
- width: 92px;
- height: 95px;
- border: 1px solid ${({ theme }) => theme.borderColors.disabled};
- border-radius: ${({ theme }) => theme.borderRadius.xs};
- background: ${({ theme }) => theme.colors.gray1};
- cursor: pointer;
-
- & > input {
- display: none;
- }
-`;
-
const PreviewImageWrapper = styled.div`
display: flex;
flex-direction: column;
diff --git a/src/components/Common/ImageUploader/imageUploader.css.ts b/src/components/Common/ImageUploader/imageUploader.css.ts
new file mode 100644
index 00000000..daa2d59e
--- /dev/null
+++ b/src/components/Common/ImageUploader/imageUploader.css.ts
@@ -0,0 +1,17 @@
+import { vars } from '@/styles/theme.css';
+import { style } from '@vanilla-extract/css';
+
+export const uploadLabel = style({
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 80,
+ height: 80,
+ backgroundColor: vars.colors.background.category,
+ borderRadius: 6,
+ cursor: 'pointer',
+});
+
+export const uploadInput = style({
+ display: 'none',
+});
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index a2e68400..0503185f 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -1,13 +1,14 @@
-import { Button, Divider, Heading, Spacing, Text, theme, useToastActionContext } from '@fun-eat/design-system';
+import { Button, Heading, Spacing, Text, theme, useToastActionContext } from '@fun-eat/design-system';
import type { FormEventHandler, RefObject } from 'react';
import styled from 'styled-components';
+import { itemTitle } from './reviewRegisterForm.css';
import RebuyCheckbox from '../RebuyCheckbox/RebuyCheckbox';
import ReviewTagList from '../ReviewTagList/ReviewTagList';
import ReviewTextarea from '../ReviewTextarea/ReviewTextarea';
import StarRate from '../StarRate/StarRate';
-import { ImageUploader, SvgIcon } from '@/components/Common';
+import { ImageUploader } from '@/components/Common';
import { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
import { useFormData, useImageUploader, useScroll } from '@/hooks/common';
import { useReviewFormActionContext, useReviewFormValueContext } from '@/hooks/context';
@@ -80,50 +81,26 @@ const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog, initTabMe
};
return (
-
- 리뷰 작성
-
-
-
-
-
-
-
-
- 구매한 상품 사진이 있다면 올려주세요.
-
-
-
- (사진은 5MB 이하, 1장까지 업로드 할 수 있어요.)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [작성시 유의사항] 신뢰성 확보에 저해되는 게시물은 삭제하거나 보이지 않게 할 수 있습니다.
-
-
-
- {isValid ? '리뷰 등록하기' : '꼭 입력해야 하는 항목이 있어요'}
-
-
-
+
);
};
diff --git a/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
new file mode 100644
index 00000000..e626aa63
--- /dev/null
+++ b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
@@ -0,0 +1,7 @@
+import { style } from '@vanilla-extract/css';
+
+export const itemTitle = style({
+ fontSize: '1.3rem',
+ fontWeight: 600,
+ marginBottom: 8,
+});
From d23ce061bbe8fedb300cde4a7e951e83da4b19b3 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sat, 6 Apr 2024 19:05:48 +0200
Subject: [PATCH 03/27] =?UTF-8?q?feat:=20=EB=B3=84=EC=A0=90=20=EC=9E=91?=
=?UTF-8?q?=EC=84=B1=20=EA=B0=9C=ED=8E=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ReviewRegisterForm/ReviewRegisterForm.tsx | 4 +-
.../StarRate/StarRate.stories.tsx | 0
.../StarRate/StarRate.tsx | 52 +++++++------------
.../StarRate/starRate.css.ts | 10 ++++
.../reviewRegisterForm.css.ts | 5 ++
5 files changed, 37 insertions(+), 34 deletions(-)
rename src/components/Review/{ => ReviewRegisterForm}/StarRate/StarRate.stories.tsx (100%)
rename src/components/Review/{ => ReviewRegisterForm}/StarRate/StarRate.tsx (51%)
create mode 100644 src/components/Review/ReviewRegisterForm/StarRate/starRate.css.ts
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index 0503185f..49a269d3 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -3,10 +3,10 @@ import type { FormEventHandler, RefObject } from 'react';
import styled from 'styled-components';
import { itemTitle } from './reviewRegisterForm.css';
+import StarRate from './StarRate/StarRate';
import RebuyCheckbox from '../RebuyCheckbox/RebuyCheckbox';
import ReviewTagList from '../ReviewTagList/ReviewTagList';
import ReviewTextarea from '../ReviewTextarea/ReviewTextarea';
-import StarRate from '../StarRate/StarRate';
import { ImageUploader } from '@/components/Common';
import { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
@@ -88,7 +88,7 @@ const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog, initTabMe
-
+
diff --git a/src/components/Review/StarRate/StarRate.stories.tsx b/src/components/Review/ReviewRegisterForm/StarRate/StarRate.stories.tsx
similarity index 100%
rename from src/components/Review/StarRate/StarRate.stories.tsx
rename to src/components/Review/ReviewRegisterForm/StarRate/StarRate.stories.tsx
diff --git a/src/components/Review/StarRate/StarRate.tsx b/src/components/Review/ReviewRegisterForm/StarRate/StarRate.tsx
similarity index 51%
rename from src/components/Review/StarRate/StarRate.tsx
rename to src/components/Review/ReviewRegisterForm/StarRate/StarRate.tsx
index ad2cd4c3..47752b2f 100644
--- a/src/components/Review/StarRate/StarRate.tsx
+++ b/src/components/Review/ReviewRegisterForm/StarRate/StarRate.tsx
@@ -1,9 +1,10 @@
-import { Button, Heading, Spacing, theme } from '@fun-eat/design-system';
-import styled from 'styled-components';
+import { starIcon, starWrapper } from './starRate.css';
+import { itemTitle, requiredMark } from '../reviewRegisterForm.css';
import { SvgIcon } from '@/components/Common';
import { useReviewFormActionContext } from '@/hooks/context';
import { useStarRatingHover } from '@/hooks/review';
+import { vars } from '@/styles/theme.css';
const starList = Array.from({ length: 5 }, (_, index) => index + 1);
@@ -20,48 +21,35 @@ const StarRate = ({ rating }: StarRateProps) => {
};
return (
-
-
- 별점을 남겨주세요.
- *
-
-
-
+
+
+ 별점
+
+ *
+
+
+
{starList.map((star) => (
-
+
))}
-
+
);
};
export default StarRate;
-
-const StarRateContainer = styled.div`
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
-`;
-
-const RequiredMark = styled.sup`
- color: ${({ theme }) => theme.colors.error};
-`;
-
-const SvgIconWrapper = styled(SvgIcon)`
- transition: all 0.3s ease-out;
-`;
diff --git a/src/components/Review/ReviewRegisterForm/StarRate/starRate.css.ts b/src/components/Review/ReviewRegisterForm/StarRate/starRate.css.ts
new file mode 100644
index 00000000..89b2c801
--- /dev/null
+++ b/src/components/Review/ReviewRegisterForm/StarRate/starRate.css.ts
@@ -0,0 +1,10 @@
+import { style } from '@vanilla-extract/css';
+
+export const starWrapper = style({
+ display: 'flex',
+ gap: 8,
+});
+
+export const starIcon = style({
+ transition: 'all 0.3s ease-out',
+});
diff --git a/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
index e626aa63..21bd73ba 100644
--- a/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
+++ b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
@@ -1,3 +1,4 @@
+import { vars } from '@/styles/theme.css';
import { style } from '@vanilla-extract/css';
export const itemTitle = style({
@@ -5,3 +6,7 @@ export const itemTitle = style({
fontWeight: 600,
marginBottom: 8,
});
+
+export const requiredMark = style({
+ color: vars.colors.error,
+});
From 5d15c1a7f6c6f61ad5f11b71b82aa6c36d6ae768 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sat, 6 Apr 2024 19:22:36 +0200
Subject: [PATCH 04/27] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EC=84=A4?=
=?UTF-8?q?=EB=AA=85=20=EA=B0=9C=ED=8E=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ReviewRegisterForm/ReviewRegisterForm.tsx | 47 ++-----------------
.../ReviewTextarea/ReviewTextarea.stories.tsx | 0
.../ReviewTextarea/ReviewTextarea.tsx | 40 ++++++++--------
.../ReviewTextarea/reviewTextarea.css.ts | 40 ++++++++++++++++
4 files changed, 64 insertions(+), 63 deletions(-)
rename src/components/Review/{ => ReviewRegisterForm}/ReviewTextarea/ReviewTextarea.stories.tsx (100%)
rename src/components/Review/{ => ReviewRegisterForm}/ReviewTextarea/ReviewTextarea.tsx (53%)
create mode 100644 src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index 49a269d3..0ee1f9f3 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -1,12 +1,11 @@
-import { Button, Heading, Spacing, Text, theme, useToastActionContext } from '@fun-eat/design-system';
+import { Spacing, Text, theme, useToastActionContext } from '@fun-eat/design-system';
import type { FormEventHandler, RefObject } from 'react';
-import styled from 'styled-components';
import { itemTitle } from './reviewRegisterForm.css';
+import ReviewTextarea from './ReviewTextarea/ReviewTextarea';
import StarRate from './StarRate/StarRate';
import RebuyCheckbox from '../RebuyCheckbox/RebuyCheckbox';
import ReviewTagList from '../ReviewTagList/ReviewTagList';
-import ReviewTextarea from '../ReviewTextarea/ReviewTextarea';
import { ImageUploader } from '@/components/Common';
import { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
@@ -90,9 +89,9 @@ const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog, initTabMe
-
+
-
+
@@ -105,41 +104,3 @@ const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog, initTabMe
};
export default ReviewRegisterForm;
-
-const ReviewRegisterFormContainer = styled.div`
- position: relative;
- height: 100%;
-`;
-
-const ReviewHeading = styled(Heading)`
- height: 80px;
- font-size: 2.4rem;
- line-height: 80px;
- text-align: center;
-`;
-
-const CloseButton = styled(Button)`
- position: absolute;
- top: 24px;
- right: 32px;
-`;
-
-const ProductOverviewItemWrapper = styled.div`
- margin: 15px 0;
-`;
-
-const RegisterForm = styled.form`
- padding: 50px 20px;
-`;
-
-const ReviewImageUploaderContainer = styled.div`
- display: flex;
- flex-direction: column;
- align-items: center;
-`;
-
-const FormButton = styled(Button)`
- color: ${({ theme, disabled }) => (disabled ? theme.colors.white : theme.colors.black)};
- background: ${({ theme, disabled }) => (disabled ? theme.colors.gray3 : theme.colors.primary)};
- cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
-`;
diff --git a/src/components/Review/ReviewTextarea/ReviewTextarea.stories.tsx b/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.stories.tsx
similarity index 100%
rename from src/components/Review/ReviewTextarea/ReviewTextarea.stories.tsx
rename to src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.stories.tsx
diff --git a/src/components/Review/ReviewTextarea/ReviewTextarea.tsx b/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
similarity index 53%
rename from src/components/Review/ReviewTextarea/ReviewTextarea.tsx
rename to src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
index 8fc4bb06..afde056c 100644
--- a/src/components/Review/ReviewTextarea/ReviewTextarea.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
@@ -1,7 +1,10 @@
-import { Heading, Spacing, Text, Textarea, useTheme } from '@fun-eat/design-system';
import type { ChangeEventHandler } from 'react';
import styled from 'styled-components';
+import { container, currentLength, reviewTextarea, status, statusWrapper } from './reviewTextarea.css';
+import { itemTitle, requiredMark } from '../reviewRegisterForm.css';
+
+import { Text } from '@/components/Common';
import { useReviewFormActionContext } from '@/hooks/context';
const MAX_LENGTH = 200;
@@ -12,32 +15,33 @@ interface ReviewTextareaProps {
const ReviewTextarea = ({ content }: ReviewTextareaProps) => {
const { handleReviewFormValue } = useReviewFormActionContext();
- const theme = useTheme();
const handleReviewText: ChangeEventHandler = (event) => {
handleReviewFormValue({ target: 'content', value: event.currentTarget.value });
};
return (
-
-
- 리뷰를 남겨주세요.
- *
-
-
-
+
+
+ {content.length}/{MAX_LENGTH}
+
+
+
);
};
@@ -53,7 +57,3 @@ const ReviewTextareaContainer = styled.div`
const RequiredMark = styled.sup`
color: ${({ theme }) => theme.colors.error};
`;
-
-const ReviewWritingStatusText = styled(Text)`
- margin-left: auto;
-`;
diff --git a/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts b/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts
new file mode 100644
index 00000000..3942d4bd
--- /dev/null
+++ b/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts
@@ -0,0 +1,40 @@
+import { vars } from '@/styles/theme.css';
+import { style } from '@vanilla-extract/css';
+
+export const container = style({
+ position: 'relative',
+});
+
+export const reviewTextarea = style({
+ width: '100%',
+ padding: '12px 16px',
+ fontSize: '1.2rem',
+ backgroundColor: vars.colors.background.category,
+ border: 'none',
+ resize: 'vertical',
+
+ selectors: {
+ '&::placeholder': {
+ fontSize: '1.2rem',
+ fontWeight: 500,
+ color: vars.colors.gray3,
+ },
+ },
+});
+
+export const statusWrapper = style({
+ position: 'absolute',
+ bottom: 12,
+ right: 16,
+});
+
+export const status = style({
+ fontSize: '1.2rem',
+ fontWeight: 500,
+ color: vars.colors.gray3,
+});
+
+export const currentLength = style({
+ color: vars.colors.black,
+ fontWeight: 500,
+});
From b52185ddd9ddd3450b4c475edec22c2dd1426852 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sat, 6 Apr 2024 20:46:30 +0200
Subject: [PATCH 05/27] =?UTF-8?q?refactor:=20=EC=95=88=20=EC=93=B0?=
=?UTF-8?q?=EB=8A=94=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=ED=8C=8C=EC=9D=BC=20?=
=?UTF-8?q?=EC=82=AD=EC=A0=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ReviewTextarea/ReviewTextarea.tsx | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx b/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
index afde056c..7500b4d7 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
@@ -1,5 +1,4 @@
import type { ChangeEventHandler } from 'react';
-import styled from 'styled-components';
import { container, currentLength, reviewTextarea, status, statusWrapper } from './reviewTextarea.css';
import { itemTitle, requiredMark } from '../reviewRegisterForm.css';
@@ -46,14 +45,3 @@ const ReviewTextarea = ({ content }: ReviewTextareaProps) => {
};
export default ReviewTextarea;
-
-const ReviewTextareaContainer = styled.div`
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
-`;
-
-const RequiredMark = styled.sup`
- color: ${({ theme }) => theme.colors.error};
-`;
From 4de7de72974c2a716c6b795ecdb0d6a17e3af513 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sat, 6 Apr 2024 20:46:44 +0200
Subject: [PATCH 06/27] =?UTF-8?q?feat:=20=EC=9E=AC=EA=B5=AC=EB=A7=A4=20?=
=?UTF-8?q?=EC=B2=B4=ED=81=AC=EB=B0=95=EC=8A=A4=20=EA=B0=9C=ED=8E=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Review/RebuyCheckbox/RebuyCheckbox.tsx | 21 ++++++++++---
.../Review/RebuyCheckbox/rebuyCheckbox.css.ts | 31 +++++++++++++++++++
.../ReviewRegisterForm/ReviewRegisterForm.tsx | 10 ++----
3 files changed, 50 insertions(+), 12 deletions(-)
create mode 100644 src/components/Review/RebuyCheckbox/rebuyCheckbox.css.ts
diff --git a/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx b/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx
index 9f1a6e95..f29357d6 100644
--- a/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx
+++ b/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx
@@ -1,10 +1,17 @@
-import { Checkbox } from '@fun-eat/design-system';
import type { ChangeEventHandler } from 'react';
+import { check, checkbox, container, label } from './rebuyCheckbox.css';
+
+import { SvgIcon } from '@/components/Common';
import { useEnterKeyDown } from '@/hooks/common';
import { useReviewFormActionContext } from '@/hooks/context';
+import { vars } from '@/styles/theme.css';
+
+interface RebuyCheckboxProps {
+ isRebuy: boolean;
+}
-const RebuyCheckbox = () => {
+const RebuyCheckbox = ({ isRebuy }: RebuyCheckboxProps) => {
const { handleReviewFormValue } = useReviewFormActionContext();
const { inputRef, labelRef, handleKeydown } = useEnterKeyDown();
@@ -14,9 +21,13 @@ const RebuyCheckbox = () => {
return (
-
- 재구매할 생각이 있으신가요?
-
+
);
};
diff --git a/src/components/Review/RebuyCheckbox/rebuyCheckbox.css.ts b/src/components/Review/RebuyCheckbox/rebuyCheckbox.css.ts
new file mode 100644
index 00000000..363515b9
--- /dev/null
+++ b/src/components/Review/RebuyCheckbox/rebuyCheckbox.css.ts
@@ -0,0 +1,31 @@
+import { vars } from '@/styles/theme.css';
+import { style, styleVariants } from '@vanilla-extract/css';
+
+export const container = style({
+ display: 'inline-flex',
+ alignItems: 'center',
+ gap: 8,
+ cursor: 'pointer',
+});
+
+export const checkbox = style({
+ display: 'none',
+});
+
+const checkBase = style({
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 17,
+ height: 17,
+ borderRadius: '50%',
+});
+
+export const check = styleVariants({
+ default: [checkBase, { backgroundColor: vars.colors.icon.light }],
+ checked: [checkBase, { backgroundColor: vars.colors.black }],
+});
+
+export const label = style({
+ fontWeight: 600,
+});
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index 0ee1f9f3..7ea74819 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -1,4 +1,4 @@
-import { Spacing, Text, theme, useToastActionContext } from '@fun-eat/design-system';
+import { Spacing, useToastActionContext } from '@fun-eat/design-system';
import type { FormEventHandler, RefObject } from 'react';
import { itemTitle } from './reviewRegisterForm.css';
@@ -93,12 +93,8 @@ const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog, initTabMe
-
-
-
-
- [작성시 유의사항] 신뢰성 확보에 저해되는 게시물은 삭제하거나 보이지 않게 할 수 있습니다.
-
+
+
);
};
From ab164c690074831b78a491248bcb6138bec166b5 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sat, 6 Apr 2024 20:49:59 +0200
Subject: [PATCH 07/27] =?UTF-8?q?feat:=20=EC=9E=AC=EA=B5=AC=EB=A7=A4=20?=
=?UTF-8?q?=ED=83=80=EC=9D=B4=ED=8B=80=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Review/RebuyCheckbox/RebuyCheckbox.tsx | 24 ++++++++++++-------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx b/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx
index f29357d6..093b58e2 100644
--- a/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx
+++ b/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx
@@ -1,6 +1,7 @@
import type { ChangeEventHandler } from 'react';
import { check, checkbox, container, label } from './rebuyCheckbox.css';
+import { itemTitle } from '../ReviewRegisterForm/reviewRegisterForm.css';
import { SvgIcon } from '@/components/Common';
import { useEnterKeyDown } from '@/hooks/common';
@@ -20,15 +21,20 @@ const RebuyCheckbox = ({ isRebuy }: RebuyCheckboxProps) => {
};
return (
-
-
-
+ <>
+
+ 재구매 여부
+
+
+
+
+ >
);
};
From c07090d11921e28d6778f8d030129cc61edba3fb Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 7 Apr 2024 12:20:08 +0200
Subject: [PATCH 08/27] =?UTF-8?q?feat:=20=ED=83=9C=EA=B7=B8=20=EC=84=A0?=
=?UTF-8?q?=ED=83=9D=20=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=20=EC=97=B4?=
=?UTF-8?q?=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ReviewRegisterForm/ReviewRegisterForm.tsx | 36 ++++++++++---------
.../reviewRegisterForm.css.ts | 13 +++++++
2 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index 7ea74819..72a80478 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -1,17 +1,16 @@
import { Spacing, useToastActionContext } from '@fun-eat/design-system';
-import type { FormEventHandler, RefObject } from 'react';
+import type { FormEventHandler } from 'react';
+import { useNavigate } from 'react-router-dom';
-import { itemTitle } from './reviewRegisterForm.css';
+import { itemTitle, requiredMark, tagAddButton } from './reviewRegisterForm.css';
import ReviewTextarea from './ReviewTextarea/ReviewTextarea';
import StarRate from './StarRate/StarRate';
import RebuyCheckbox from '../RebuyCheckbox/RebuyCheckbox';
-import ReviewTagList from '../ReviewTagList/ReviewTagList';
import { ImageUploader } from '@/components/Common';
import { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
-import { useFormData, useImageUploader, useScroll } from '@/hooks/common';
+import { useFormData, useImageUploader } from '@/hooks/common';
import { useReviewFormActionContext, useReviewFormValueContext } from '@/hooks/context';
-import { useProductDetailQuery } from '@/hooks/queries/product';
import { useReviewRegisterFormMutation } from '@/hooks/queries/review';
import type { ReviewRequest } from '@/types/review';
@@ -21,21 +20,18 @@ const MIN_CONTENT_LENGTH = 0;
interface ReviewRegisterFormProps {
productId: number;
- targetRef: RefObject;
- closeReviewDialog: () => void;
- initTabMenu: () => void;
+ openBottomSheet: () => void;
}
-const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog, initTabMenu }: ReviewRegisterFormProps) => {
- const { scrollToPosition } = useScroll();
+const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormProps) => {
const { isImageUploading, previewImage, imageFile, uploadImage, deleteImage } = useImageUploader();
+ const navigate = useNavigate();
const reviewFormValue = useReviewFormValueContext();
const { resetReviewFormValue } = useReviewFormActionContext();
const { toast } = useToastActionContext();
- const { data: productDetail } = useProductDetailQuery(productId);
- const { mutate, isLoading } = useReviewRegisterFormMutation(productId);
+ const { mutate } = useReviewRegisterFormMutation(productId);
const isValid =
reviewFormValue.rating > MIN_RATING_SCORE &&
@@ -54,7 +50,6 @@ const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog, initTabMe
const resetAndCloseForm = () => {
deleteImage();
resetReviewFormValue();
- closeReviewDialog();
};
const handleSubmit: FormEventHandler = async (event) => {
@@ -63,9 +58,8 @@ const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog, initTabMe
mutate(formData, {
onSuccess: () => {
resetAndCloseForm();
- initTabMenu();
- scrollToPosition(targetRef);
toast.success('📝 리뷰가 등록 됐어요');
+ navigate(-1);
},
onError: (error) => {
resetAndCloseForm();
@@ -90,7 +84,17 @@ const ReviewRegisterForm = ({ productId, targetRef, closeReviewDialog, initTabMe
-
+
+
+ 태그
+
+ *
+
+
+
+
diff --git a/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
index 21bd73ba..f407e804 100644
--- a/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
+++ b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
@@ -10,3 +10,16 @@ export const itemTitle = style({
export const requiredMark = style({
color: vars.colors.error,
});
+
+export const tagAddButton = style({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ width: '100%',
+ height: 44,
+ fontSize: '1.4rem',
+ fontWeight: 500,
+ borderRadius: 6,
+ border: `1px solid ${vars.colors.border.default}`,
+ color: vars.colors.gray3,
+});
From 1bdbe2b73192cb52f36da3701e35533b090391c2 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 7 Apr 2024 12:24:31 +0200
Subject: [PATCH 09/27] =?UTF-8?q?feat:=20=ED=83=9C=EA=B7=B8=20=EC=84=A0?=
=?UTF-8?q?=ED=83=9D=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Review/ReviewTagList/ReviewTagList.tsx | 109 +++++-------------
.../Review/ReviewTagList/reviewTagList.css.ts | 42 +++++++
2 files changed, 69 insertions(+), 82 deletions(-)
create mode 100644 src/components/Review/ReviewTagList/reviewTagList.css.ts
diff --git a/src/components/Review/ReviewTagList/ReviewTagList.tsx b/src/components/Review/ReviewTagList/ReviewTagList.tsx
index 715e6165..af960947 100644
--- a/src/components/Review/ReviewTagList/ReviewTagList.tsx
+++ b/src/components/Review/ReviewTagList/ReviewTagList.tsx
@@ -1,93 +1,38 @@
-import { Heading, Spacing } from '@fun-eat/design-system';
-import styled from 'styled-components';
-
-import ReviewTagItem from '../ReviewTagItem/ReviewTagItem';
+import { checkbox, container, itemTitle, tagLabel, tagList } from './reviewTagList.css';
import { TAG_TITLE } from '@/constants';
+import { useReviewFormActionContext } from '@/hooks/context';
import { useReviewTagsQuery } from '@/hooks/queries/review';
-interface ReviewTagListProps {
- selectedTags: number[];
-}
-
-const ReviewTagList = ({ selectedTags }: ReviewTagListProps) => {
+const ReviewTagList = () => {
const { data: tagsData } = useReviewTagsQuery();
+ const { handleReviewFormValue } = useReviewFormActionContext();
+
+ const handleTagSelect = (tagId: number) => () => {
+ handleReviewFormValue({ target: 'tagIds', value: tagId });
+ };
return (
-
-
- 태그를 골라주세요. (3개까지)
- *
-
-
-
- {tagsData.map(({ tagType, tags }) => (
-
-
- {TAG_TITLE[tagType]}
-
-
-
- {tags.map(({ id, name }) => (
- <>
- -
-
-
-
- >
- ))}
-
-
- ))}
-
-
-
+
+ {tagsData.map(({ tagType, tags }) => (
+
+
+ {TAG_TITLE[tagType]}
+
+
+
+ ))}
+
);
};
export default ReviewTagList;
-
-const ReviewTagListContainer = styled.div`
- display: flex;
- flex-direction: column;
- align-items: center;
-`;
-
-const RequiredMark = styled.sup`
- color: ${({ theme }) => theme.colors.error};
-`;
-
-const TagListWrapper = styled.div`
- display: flex;
- width: 100%;
- margin: 0 auto;
- column-gap: 20px;
- overflow-x: auto;
-
- @media screen and (min-width: 420px) {
- justify-content: center;
-
- & > div {
- flex-grow: 0;
- }
- }
-
- &::-webkit-scrollbar {
- display: none;
- }
-
- & > div {
- flex-grow: 1;
- }
-`;
-
-const TagItemWrapper = styled.div`
- display: flex;
- flex-direction: column;
- align-items: center;
- min-width: 100px;
-`;
-
-const TagTitle = styled(Heading)`
- text-align: center;
-`;
diff --git a/src/components/Review/ReviewTagList/reviewTagList.css.ts b/src/components/Review/ReviewTagList/reviewTagList.css.ts
new file mode 100644
index 00000000..c2928da9
--- /dev/null
+++ b/src/components/Review/ReviewTagList/reviewTagList.css.ts
@@ -0,0 +1,42 @@
+import { vars } from '@/styles/theme.css';
+import { style } from '@vanilla-extract/css';
+
+export const container = style({
+ display: 'flex',
+ flexDirection: 'column',
+ gap: 32,
+});
+
+export const itemTitle = style({
+ fontSize: '1.6rem',
+ fontWeight: 600,
+ marginBottom: 12,
+});
+
+export const tagList = style({
+ display: 'flex',
+ flexWrap: 'wrap',
+ gap: 4,
+});
+
+export const checkbox = style({
+ display: 'none',
+});
+
+export const tagLabel = style({
+ display: 'inline-block',
+ padding: '6px 12px',
+ borderRadius: 30,
+ backgroundColor: vars.colors.background.category,
+ fontSize: '1.4rem',
+ fontWeight: 500,
+ cursor: 'pointer',
+ userSelect: 'none',
+
+ selectors: {
+ [`${checkbox}:checked + &`]: {
+ backgroundColor: vars.colors.gray5,
+ color: vars.colors.white,
+ },
+ },
+});
From 1406cd2535b1ed32aebb122c6379442759f7f9fd Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 7 Apr 2024 12:54:14 +0200
Subject: [PATCH 10/27] =?UTF-8?q?feat:=20=ED=83=9C=EA=B7=B8=20=EC=B5=9C?=
=?UTF-8?q?=EB=8C=80=203=EA=B0=9C=20=EC=84=A0=ED=83=9D=20=EA=B5=AC?=
=?UTF-8?q?=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ReviewRegisterForm/ReviewRegisterForm.tsx | 8 ++--
.../Review/ReviewTagList/ReviewTagList.tsx | 24 ++++++----
src/contexts/ReviewFormContext.tsx | 45 ++++++++++++++-----
3 files changed, 54 insertions(+), 23 deletions(-)
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index 72a80478..678dba6d 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -35,16 +35,18 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr
const isValid =
reviewFormValue.rating > MIN_RATING_SCORE &&
- reviewFormValue.tagIds.length >= MIN_SELECTED_TAGS_COUNT &&
- reviewFormValue.tagIds.length <= MIN_DISPLAYED_TAGS_LENGTH &&
+ reviewFormValue.tags.length >= MIN_SELECTED_TAGS_COUNT &&
+ reviewFormValue.tags.length <= MIN_DISPLAYED_TAGS_LENGTH &&
reviewFormValue.content.length > MIN_CONTENT_LENGTH &&
!isImageUploading;
+ const formValue: ReviewRequest = { ...reviewFormValue, tagIds: reviewFormValue.tags.map(({ id }) => id) };
+
const formData = useFormData({
imageKey: 'image',
imageFile: imageFile,
formContentKey: 'reviewRequest',
- formContent: reviewFormValue,
+ formContent: formValue,
});
const resetAndCloseForm = () => {
diff --git a/src/components/Review/ReviewTagList/ReviewTagList.tsx b/src/components/Review/ReviewTagList/ReviewTagList.tsx
index af960947..b9b0634c 100644
--- a/src/components/Review/ReviewTagList/ReviewTagList.tsx
+++ b/src/components/Review/ReviewTagList/ReviewTagList.tsx
@@ -1,15 +1,23 @@
+import type { ChangeEvent } from 'react';
+
import { checkbox, container, itemTitle, tagLabel, tagList } from './reviewTagList.css';
-import { TAG_TITLE } from '@/constants';
-import { useReviewFormActionContext } from '@/hooks/context';
+import { MIN_DISPLAYED_TAGS_LENGTH, TAG_TITLE } from '@/constants';
+import type { TagValue } from '@/contexts/ReviewFormContext';
+import { useReviewFormActionContext, useReviewFormValueContext } from '@/hooks/context';
import { useReviewTagsQuery } from '@/hooks/queries/review';
const ReviewTagList = () => {
const { data: tagsData } = useReviewTagsQuery();
+ const { tags: selectedTags } = useReviewFormValueContext();
const { handleReviewFormValue } = useReviewFormActionContext();
- const handleTagSelect = (tagId: number) => () => {
- handleReviewFormValue({ target: 'tagIds', value: tagId });
+ const handleTagSelect = (currentTag: TagValue) => (event: ChangeEvent) => {
+ handleReviewFormValue({ target: 'tags', value: currentTag });
+
+ if (selectedTags.length >= MIN_DISPLAYED_TAGS_LENGTH) {
+ event.target.checked = false;
+ }
};
return (
@@ -20,11 +28,11 @@ const ReviewTagList = () => {
{TAG_TITLE[tagType]}
- {tags.map(({ id, name }) => (
- -
+ {tags.map((tag) => (
+
-
))}
diff --git a/src/contexts/ReviewFormContext.tsx b/src/contexts/ReviewFormContext.tsx
index 8be4fb1f..94b974ce 100644
--- a/src/contexts/ReviewFormContext.tsx
+++ b/src/contexts/ReviewFormContext.tsx
@@ -3,12 +3,19 @@ import type { PropsWithChildren } from 'react';
import { createContext, useState } from 'react';
import { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
-import type { ReviewRequest, ReviewRequestKey } from '@/types/review';
+import type { ReviewRequest } from '@/types/review';
+
+export interface TagValue {
+ id: number;
+ name: string;
+}
+
+type ReviewFormValue = Omit & { tags: TagValue[] };
+type ReviewFormValues = Exclude | TagValue;
interface ReviewFormActionParams {
- target: ReviewRequestKey;
- value: string | number | boolean;
- isSelected?: boolean;
+ target: keyof ReviewFormValue;
+ value: ReviewFormValues;
}
interface ReviewFormAction {
@@ -16,31 +23,45 @@ interface ReviewFormAction {
resetReviewFormValue: () => void;
}
-const initialReviewFormValue: ReviewRequest = {
+const initialReviewFormValue: ReviewFormValue = {
rating: 0,
- tagIds: [],
+ tags: [],
content: '',
rebuy: false,
};
-export const ReviewFormValueContext = createContext(null);
+const MIN_RATING_SCORE = 0;
+const MIN_SELECTED_TAGS_COUNT = 1;
+const MIN_CONTENT_LENGTH = 0;
+
+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 ReviewFormActionContext = createContext(null);
const ReviewFormProvider = ({ children }: PropsWithChildren) => {
const [reviewFormValue, setReviewFormValue] = useState(initialReviewFormValue);
const { toast } = useToastActionContext();
- const handleReviewFormValue = ({ target, value, isSelected }: ReviewFormActionParams) => {
+ const isValid =
+ reviewFormValue.rating > MIN_RATING_SCORE &&
+ reviewFormValue.tags.length >= MIN_SELECTED_TAGS_COUNT &&
+ reviewFormValue.tags.length <= MIN_DISPLAYED_TAGS_LENGTH &&
+ reviewFormValue.content.length > MIN_CONTENT_LENGTH;
+
+ const handleReviewFormValue = ({ target, value }: ReviewFormActionParams) => {
setReviewFormValue((prev) => {
const targetValue = prev[target];
- if (Array.isArray(targetValue)) {
- if (targetValue.length >= MIN_DISPLAYED_TAGS_LENGTH && !isSelected) {
- toast.success(`태그는 ${MIN_DISPLAYED_TAGS_LENGTH}개까지 선택할 수 있습니다`);
+ if (isTagValue(value) && Array.isArray(targetValue)) {
+ if (targetValue.length >= MIN_DISPLAYED_TAGS_LENGTH && !isSelectedTag(targetValue, value)) {
+ toast.error(`태그는 ${MIN_DISPLAYED_TAGS_LENGTH}개까지 선택할 수 있습니다`);
return prev;
}
- if (isSelected) {
+ if (isSelectedTag(targetValue, value)) {
return { ...prev, [target]: targetValue.filter((tagId) => tagId !== value) };
}
From 799d27c84446f41b7cfab452a9cee2da12b49208 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 7 Apr 2024 13:04:33 +0200
Subject: [PATCH 11/27] =?UTF-8?q?feat:=20=EC=B2=B4=ED=81=AC=20=EB=90=98?=
=?UTF-8?q?=EC=96=B4=20=EC=9E=88=EB=8A=94=20=ED=83=9C=EA=B7=B8=20=EC=8A=A4?=
=?UTF-8?q?=ED=83=80=EC=9D=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/Review/ReviewTagList/ReviewTagList.tsx | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/components/Review/ReviewTagList/ReviewTagList.tsx b/src/components/Review/ReviewTagList/ReviewTagList.tsx
index b9b0634c..6773772e 100644
--- a/src/components/Review/ReviewTagList/ReviewTagList.tsx
+++ b/src/components/Review/ReviewTagList/ReviewTagList.tsx
@@ -12,6 +12,8 @@ const ReviewTagList = () => {
const { tags: selectedTags } = useReviewFormValueContext();
const { handleReviewFormValue } = useReviewFormActionContext();
+ const isChecked = (tag: TagValue) => selectedTags.some(({ id }) => id === tag.id);
+
const handleTagSelect = (currentTag: TagValue) => (event: ChangeEvent) => {
handleReviewFormValue({ target: 'tags', value: currentTag });
@@ -31,7 +33,12 @@ const ReviewTagList = () => {
{tags.map((tag) => (
-
From 965ec0e5e5d67eef9e08b85b4b3ceee68978173d Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 7 Apr 2024 13:15:31 +0200
Subject: [PATCH 12/27] =?UTF-8?q?feat:=20=EC=84=A0=ED=83=9D=20=ED=83=9C?=
=?UTF-8?q?=EA=B7=B8=20=ED=8F=BC=EC=97=90=EC=84=9C=20=EB=A0=8C=EB=8D=94?=
=?UTF-8?q?=EB=A7=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ReviewRegisterForm/ReviewRegisterForm.tsx | 15 +++++++++++++--
.../reviewRegisterForm.css.ts | 19 +++++++++++++++++++
2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index 678dba6d..7c7c00dd 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -2,16 +2,17 @@ import { Spacing, useToastActionContext } from '@fun-eat/design-system';
import type { FormEventHandler } from 'react';
import { useNavigate } from 'react-router-dom';
-import { itemTitle, requiredMark, tagAddButton } from './reviewRegisterForm.css';
+import { itemTitle, requiredMark, tagAddButton, tagButton, tagList } from './reviewRegisterForm.css';
import ReviewTextarea from './ReviewTextarea/ReviewTextarea';
import StarRate from './StarRate/StarRate';
import RebuyCheckbox from '../RebuyCheckbox/RebuyCheckbox';
-import { ImageUploader } from '@/components/Common';
+import { ImageUploader, SvgIcon } from '@/components/Common';
import { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
import { useFormData, useImageUploader } from '@/hooks/common';
import { useReviewFormActionContext, useReviewFormValueContext } from '@/hooks/context';
import { useReviewRegisterFormMutation } from '@/hooks/queries/review';
+import { vars } from '@/styles/theme.css';
import type { ReviewRequest } from '@/types/review';
const MIN_RATING_SCORE = 0;
@@ -96,6 +97,16 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr
+
+ {reviewFormValue.tags.map((tag) => (
+ -
+
+
+ ))}
+
diff --git a/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
index f407e804..f9e43fc2 100644
--- a/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
+++ b/src/components/Review/ReviewRegisterForm/reviewRegisterForm.css.ts
@@ -23,3 +23,22 @@ export const tagAddButton = style({
border: `1px solid ${vars.colors.border.default}`,
color: vars.colors.gray3,
});
+
+export const tagList = style({
+ display: 'flex',
+ flexWrap: 'wrap',
+ gap: 4,
+ marginTop: 12,
+});
+
+export const tagButton = style({
+ display: 'flex',
+ alignItems: 'center',
+ gap: 4,
+ height: 28,
+ padding: '0 6px',
+ fontSize: '1.3rem',
+ fontWeight: 500,
+ borderRadius: 4,
+ backgroundColor: vars.colors.gray2,
+});
From 1bd6ac993f6505f02452abc5130ab21f2b6242ed Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 7 Apr 2024 13:17:41 +0200
Subject: [PATCH 13/27] =?UTF-8?q?feat:=20=ED=8F=BC=EC=97=90=EC=84=9C=20?=
=?UTF-8?q?=ED=83=9C=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
---
.../Review/ReviewRegisterForm/ReviewRegisterForm.tsx | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index 7c7c00dd..caf94307 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -9,6 +9,7 @@ import RebuyCheckbox from '../RebuyCheckbox/RebuyCheckbox';
import { ImageUploader, SvgIcon } from '@/components/Common';
import { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
+import type { TagValue } from '@/contexts/ReviewFormContext';
import { useFormData, useImageUploader } from '@/hooks/common';
import { useReviewFormActionContext, useReviewFormValueContext } from '@/hooks/context';
import { useReviewRegisterFormMutation } from '@/hooks/queries/review';
@@ -29,7 +30,7 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr
const navigate = useNavigate();
const reviewFormValue = useReviewFormValueContext();
- const { resetReviewFormValue } = useReviewFormActionContext();
+ const { handleReviewFormValue, resetReviewFormValue } = useReviewFormActionContext();
const { toast } = useToastActionContext();
const { mutate } = useReviewRegisterFormMutation(productId);
@@ -55,6 +56,10 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr
resetReviewFormValue();
};
+ const handleTagSelect = (currentTag: TagValue) => () => {
+ handleReviewFormValue({ target: 'tags', value: currentTag });
+ };
+
const handleSubmit: FormEventHandler = async (event) => {
event.preventDefault();
@@ -100,7 +105,7 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr
{reviewFormValue.tags.map((tag) => (
-
-
))}
diff --git a/src/components/Review/ReviewTagList/reviewTagList.css.ts b/src/components/Review/ReviewTagList/reviewTagList.css.ts
index c2928da9..5f3e50e9 100644
--- a/src/components/Review/ReviewTagList/reviewTagList.css.ts
+++ b/src/components/Review/ReviewTagList/reviewTagList.css.ts
@@ -28,8 +28,6 @@ export const tagLabel = style({
padding: '6px 12px',
borderRadius: 30,
backgroundColor: vars.colors.background.category,
- fontSize: '1.4rem',
- fontWeight: 500,
cursor: 'pointer',
userSelect: 'none',
From 52b88207595c0166d25c61d383a70ed469a8a4de Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 14 Apr 2024 13:50:34 +0200
Subject: [PATCH 20/27] =?UTF-8?q?style:=20=ED=83=9C=EA=B7=B8=20=EC=A1=B0?=
=?UTF-8?q?=EA=B1=B4=20=EC=9D=B4=EB=A6=84=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.tsx | 4 ++--
src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx | 6 +++---
src/constants/index.ts | 2 +-
src/contexts/ReviewFormContext.tsx | 8 ++++----
src/router/index.tsx | 2 +-
5 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index caf94307..3caecf3b 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -8,7 +8,7 @@ import StarRate from './StarRate/StarRate';
import RebuyCheckbox from '../RebuyCheckbox/RebuyCheckbox';
import { ImageUploader, SvgIcon } from '@/components/Common';
-import { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
+import { MAX_DISPLAYED_TAGS_LENGTH } from '@/constants';
import type { TagValue } from '@/contexts/ReviewFormContext';
import { useFormData, useImageUploader } from '@/hooks/common';
import { useReviewFormActionContext, useReviewFormValueContext } from '@/hooks/context';
@@ -38,7 +38,7 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr
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 &&
!isImageUploading;
diff --git a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx
index ea5ccb8d..0229c236 100644
--- a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx
+++ b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx
@@ -1,7 +1,7 @@
import { registerButton, registerButtonWrapper, section } from './reviewTagSheet.css';
import ReviewTagList from '../ReviewTagList/ReviewTagList';
-import { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
+import { MAX_DISPLAYED_TAGS_LENGTH } from '@/constants';
import { useReviewFormValueContext } from '@/hooks/context';
interface ReviewTagSheetProps {
@@ -11,7 +11,7 @@ interface ReviewTagSheetProps {
const ReviewTagSheet = ({ close }: ReviewTagSheetProps) => {
const { tags } = useReviewFormValueContext();
- const isValid = tags.length === MIN_DISPLAYED_TAGS_LENGTH;
+ const isValid = tags.length === MAX_DISPLAYED_TAGS_LENGTH;
return (
<>
@@ -25,7 +25,7 @@ const ReviewTagSheet = ({ close }: ReviewTagSheetProps) => {
disabled={!isValid}
onClick={() => close()}
>
- 태그 선택 완료 {tags.length}/{MIN_DISPLAYED_TAGS_LENGTH}
+ 태그 선택 완료 {tags.length}/{MAX_DISPLAYED_TAGS_LENGTH}
>
diff --git a/src/constants/index.ts b/src/constants/index.ts
index f569bd28..755e66f8 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -51,7 +51,7 @@ export const TAG_TITLE = {
ETC: '기타',
} as const;
-export const MIN_DISPLAYED_TAGS_LENGTH = 3;
+export const MAX_DISPLAYED_TAGS_LENGTH = 3;
export const CATEGORY_TYPE = {
FOOD: 'food',
diff --git a/src/contexts/ReviewFormContext.tsx b/src/contexts/ReviewFormContext.tsx
index 94b974ce..0cc00f28 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 { MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
+import { MAX_DISPLAYED_TAGS_LENGTH } from '@/constants';
import type { ReviewRequest } from '@/types/review';
export interface TagValue {
@@ -48,7 +48,7 @@ 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;
const handleReviewFormValue = ({ target, value }: ReviewFormActionParams) => {
@@ -56,8 +56,8 @@ const ReviewFormProvider = ({ children }: PropsWithChildren) => {
const targetValue = prev[target];
if (isTagValue(value) && Array.isArray(targetValue)) {
- if (targetValue.length >= MIN_DISPLAYED_TAGS_LENGTH && !isSelectedTag(targetValue, value)) {
- toast.error(`태그는 ${MIN_DISPLAYED_TAGS_LENGTH}개까지 선택할 수 있습니다`);
+ if (targetValue.length >= MAX_DISPLAYED_TAGS_LENGTH && !isSelectedTag(targetValue, value)) {
+ toast.error(`태그는 ${MAX_DISPLAYED_TAGS_LENGTH}개까지 선택할 수 있습니다`);
return prev;
}
diff --git a/src/router/index.tsx b/src/router/index.tsx
index 58efe2ca..4d7b89f8 100644
--- a/src/router/index.tsx
+++ b/src/router/index.tsx
@@ -180,7 +180,7 @@ const router = createBrowserRouter([
},
},
{
- path: `${PATH.PRODUCT_LIST}/:category/:productId/review-register`,
+ path: `${PATH.PRODUCT_LIST}/detail/:productId/review-register`,
async lazy() {
const { ReviewRegisterPage } = await import(
/* webpackChunkName: "ReviewRegisterPage" */ '@/pages/ReviewRegisterPage/ReviewRegisterPage'
From b5885e32a17a70432f447cbe2b813867f32fd248 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 14 Apr 2024 13:53:02 +0200
Subject: [PATCH 21/27] =?UTF-8?q?feat:=20=ED=83=9C=EA=B7=B8=20=EC=84=A0?=
=?UTF-8?q?=ED=83=9D=20=EC=B5=9C=EC=86=8C=20=EC=A1=B0=EA=B1=B4=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
---
src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx | 4 ++--
src/constants/index.ts | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx
index 0229c236..aadf4c4f 100644
--- a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx
+++ b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx
@@ -1,7 +1,7 @@
import { registerButton, registerButtonWrapper, section } from './reviewTagSheet.css';
import ReviewTagList from '../ReviewTagList/ReviewTagList';
-import { MAX_DISPLAYED_TAGS_LENGTH } from '@/constants';
+import { MAX_DISPLAYED_TAGS_LENGTH, MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
import { useReviewFormValueContext } from '@/hooks/context';
interface ReviewTagSheetProps {
@@ -11,7 +11,7 @@ interface ReviewTagSheetProps {
const ReviewTagSheet = ({ close }: ReviewTagSheetProps) => {
const { tags } = useReviewFormValueContext();
- const isValid = tags.length === MAX_DISPLAYED_TAGS_LENGTH;
+ const isValid = tags.length >= MIN_DISPLAYED_TAGS_LENGTH && tags.length <= MAX_DISPLAYED_TAGS_LENGTH;
return (
<>
diff --git a/src/constants/index.ts b/src/constants/index.ts
index 755e66f8..f88997f9 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -51,6 +51,7 @@ export const TAG_TITLE = {
ETC: '기타',
} as const;
+export const MIN_DISPLAYED_TAGS_LENGTH = 1;
export const MAX_DISPLAYED_TAGS_LENGTH = 3;
export const CATEGORY_TYPE = {
From 504fe9fda787fdfbe4476cdf86fcf5a33a0694d2 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 14 Apr 2024 13:58:17 +0200
Subject: [PATCH 22/27] =?UTF-8?q?feat:=20=ED=83=9C=EA=B7=B8=20=EC=84=A0?=
=?UTF-8?q?=ED=83=9D=20=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=20=EB=86=92?=
=?UTF-8?q?=EC=9D=B4=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx | 6 +++---
src/components/Review/ReviewTagSheet/reviewTagSheet.css.ts | 6 +++++-
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx
index aadf4c4f..10d5b0d8 100644
--- a/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx
+++ b/src/components/Review/ReviewTagSheet/ReviewTagSheet.tsx
@@ -1,4 +1,4 @@
-import { registerButton, registerButtonWrapper, section } from './reviewTagSheet.css';
+import { container, registerButton, registerButtonWrapper, section } from './reviewTagSheet.css';
import ReviewTagList from '../ReviewTagList/ReviewTagList';
import { MAX_DISPLAYED_TAGS_LENGTH, MIN_DISPLAYED_TAGS_LENGTH } from '@/constants';
@@ -14,7 +14,7 @@ const ReviewTagSheet = ({ close }: ReviewTagSheetProps) => {
const isValid = tags.length >= MIN_DISPLAYED_TAGS_LENGTH && tags.length <= MAX_DISPLAYED_TAGS_LENGTH;
return (
- <>
+
@@ -28,7 +28,7 @@ const ReviewTagSheet = ({ close }: ReviewTagSheetProps) => {
태그 선택 완료 {tags.length}/{MAX_DISPLAYED_TAGS_LENGTH}
- >
+
);
};
diff --git a/src/components/Review/ReviewTagSheet/reviewTagSheet.css.ts b/src/components/Review/ReviewTagSheet/reviewTagSheet.css.ts
index e4d951d0..8d689d3e 100644
--- a/src/components/Review/ReviewTagSheet/reviewTagSheet.css.ts
+++ b/src/components/Review/ReviewTagSheet/reviewTagSheet.css.ts
@@ -1,6 +1,10 @@
import { vars } from '@/styles/theme.css';
import { style, styleVariants } from '@vanilla-extract/css';
+export const container = style({
+ height: '100vh',
+});
+
export const section = style({
padding: '50px 20px 70px',
marginBottom: 32,
@@ -17,7 +21,7 @@ export const registerButtonWrapper = style({
height: 70,
maxWidth: 400,
padding: '0 20px',
- border: `1px solid ${vars.colors.border.default}`,
+ borderTop: `1px solid ${vars.colors.border.default}`,
backgroundColor: vars.colors.background.default,
transform: 'translateX(-50%)',
});
From 635a3a543ce89b0de5a529c5f6f0fe2943da0da2 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 14 Apr 2024 14:04:02 +0200
Subject: [PATCH 23/27] =?UTF-8?q?refactor:=20Text=20=EC=BB=B4=ED=8F=AC?=
=?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=82=AC=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx | 8 +++++---
src/components/Review/RebuyCheckbox/rebuyCheckbox.css.ts | 4 ----
.../Review/ReviewRegisterForm/ReviewRegisterForm.tsx | 9 ++++-----
3 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx b/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx
index 093b58e2..ee974900 100644
--- a/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx
+++ b/src/components/Review/RebuyCheckbox/RebuyCheckbox.tsx
@@ -1,9 +1,9 @@
import type { ChangeEventHandler } from 'react';
-import { check, checkbox, container, label } from './rebuyCheckbox.css';
+import { check, checkbox, container } from './rebuyCheckbox.css';
import { itemTitle } from '../ReviewRegisterForm/reviewRegisterForm.css';
-import { SvgIcon } from '@/components/Common';
+import { SvgIcon, Text } from '@/components/Common';
import { useEnterKeyDown } from '@/hooks/common';
import { useReviewFormActionContext } from '@/hooks/context';
import { vars } from '@/styles/theme.css';
@@ -31,7 +31,9 @@ const RebuyCheckbox = ({ isRebuy }: RebuyCheckboxProps) => {
- 재구매할 생각이 있어요
+
+ 재구매할 생각이 있어요
+
>
diff --git a/src/components/Review/RebuyCheckbox/rebuyCheckbox.css.ts b/src/components/Review/RebuyCheckbox/rebuyCheckbox.css.ts
index 363515b9..efb6cd1c 100644
--- a/src/components/Review/RebuyCheckbox/rebuyCheckbox.css.ts
+++ b/src/components/Review/RebuyCheckbox/rebuyCheckbox.css.ts
@@ -25,7 +25,3 @@ export const check = styleVariants({
default: [checkBase, { backgroundColor: vars.colors.icon.light }],
checked: [checkBase, { backgroundColor: vars.colors.black }],
});
-
-export const label = style({
- fontWeight: 600,
-});
diff --git a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
index 3caecf3b..dbbc0455 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewRegisterForm.tsx
@@ -7,8 +7,8 @@ import ReviewTextarea from './ReviewTextarea/ReviewTextarea';
import StarRate from './StarRate/StarRate';
import RebuyCheckbox from '../RebuyCheckbox/RebuyCheckbox';
-import { ImageUploader, SvgIcon } from '@/components/Common';
-import { MAX_DISPLAYED_TAGS_LENGTH } from '@/constants';
+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';
@@ -17,7 +17,6 @@ import { vars } from '@/styles/theme.css';
import type { ReviewRequest } from '@/types/review';
const MIN_RATING_SCORE = 0;
-const MIN_SELECTED_TAGS_COUNT = 1;
const MIN_CONTENT_LENGTH = 0;
interface ReviewRegisterFormProps {
@@ -37,7 +36,7 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr
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 &&
!isImageUploading;
@@ -106,7 +105,7 @@ const ReviewRegisterForm = ({ productId, openBottomSheet }: ReviewRegisterFormPr
{reviewFormValue.tags.map((tag) => (
- {tag.name}
+ {tag.name}
From c6e707f94591e340bb9476398dd83a5c01e96ad4 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 14 Apr 2024 14:24:34 +0200
Subject: [PATCH 24/27] =?UTF-8?q?feat:=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?=
=?UTF-8?q?=EC=97=85=EB=A1=9C=EB=8D=94=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?=
=?UTF-8?q?=EA=B0=9C=ED=8E=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Common/ImageUploader/ImageUploader.tsx | 52 ++++++++++---------
.../Common/ImageUploader/imageUploader.css.ts | 45 ++++++++++++++--
2 files changed, 69 insertions(+), 28 deletions(-)
diff --git a/src/components/Common/ImageUploader/ImageUploader.tsx b/src/components/Common/ImageUploader/ImageUploader.tsx
index 6202d0e9..5b1e99a0 100644
--- a/src/components/Common/ImageUploader/ImageUploader.tsx
+++ b/src/components/Common/ImageUploader/ImageUploader.tsx
@@ -1,9 +1,9 @@
-import { Button, useToastActionContext } from '@fun-eat/design-system';
+import { useToastActionContext } from '@fun-eat/design-system';
import type { ChangeEventHandler } from 'react';
-import styled from 'styled-components';
-import { uploadInput, uploadLabel } from './imageUploader.css';
+import { container, deleteButton, image, imageWrapper, uploadInput, uploadLabel } from './imageUploader.css';
import SvgIcon from '../Svg/SvgIcon';
+import Text from '../Text/Text';
import { IMAGE_MAX_SIZE } from '@/constants';
import { useEnterKeyDown } from '@/hooks/common';
@@ -36,30 +36,32 @@ const ImageUploader = ({ previewImage, uploadImage, deleteImage }: ReviewImageUp
};
return (
- <>
- {/*이미지 미리보기 디자인*/}
- {previewImage ? (
-
-
-
- 삭제하기
-
-
- ) : (
-
+
+
+ {previewImage && (
+
+
+
+
+
+
)}
- >
+
);
};
export default ImageUploader;
-
-const PreviewImageWrapper = styled.div`
- display: flex;
- flex-direction: column;
- gap: 20px;
- align-items: center;
-`;
diff --git a/src/components/Common/ImageUploader/imageUploader.css.ts b/src/components/Common/ImageUploader/imageUploader.css.ts
index daa2d59e..1edc9ab8 100644
--- a/src/components/Common/ImageUploader/imageUploader.css.ts
+++ b/src/components/Common/ImageUploader/imageUploader.css.ts
@@ -1,17 +1,56 @@
import { vars } from '@/styles/theme.css';
-import { style } from '@vanilla-extract/css';
+import { style, styleVariants } from '@vanilla-extract/css';
-export const uploadLabel = style({
+export const container = style({
display: 'flex',
+ gap: 8,
+});
+
+export const uploadLabelBase = style({
+ display: 'flex',
+ flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
width: 80,
height: 80,
- backgroundColor: vars.colors.background.category,
borderRadius: 6,
cursor: 'pointer',
});
+export const uploadLabel = styleVariants({
+ default: [uploadLabelBase, { backgroundColor: vars.colors.background.category }],
+ uploaded: [
+ uploadLabelBase,
+ { backgroundColor: vars.colors.background.default, border: `1px solid ${vars.colors.border.default}` },
+ ],
+});
+
export const uploadInput = style({
display: 'none',
});
+
+export const imageWrapper = style({
+ position: 'relative',
+ width: 80,
+ height: 80,
+});
+
+export const image = style({
+ objectFit: 'cover',
+ borderRadius: 6,
+});
+
+export const deleteButton = style({
+ position: 'absolute',
+ top: 4,
+ right: 4,
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ width: 18,
+ height: 18,
+ borderRadius: '50%',
+ backgroundColor: vars.colors.black,
+ opacity: 0.5,
+ cursor: 'pointer',
+});
From 1415476dccf3b739d76a354eef75929ce6fc98f4 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 14 Apr 2024 14:54:10 +0200
Subject: [PATCH 25/27] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=EC=84=A4?=
=?UTF-8?q?=EB=AA=85=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ReviewTextarea/ReviewTextarea.tsx | 27 ++++++++++++++++---
.../ReviewTextarea/reviewTextarea.css.ts | 20 +++++++++++---
2 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx b/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
index 933fe888..ea461768 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
@@ -1,12 +1,14 @@
-import type { ChangeEventHandler } from 'react';
+import { useState } from 'react';
+import type { FocusEventHandler, ChangeEventHandler } from 'react';
-import { container, currentLength, reviewTextarea, statusWrapper } from './reviewTextarea.css';
+import { container, currentLength, errorMessage, reviewTextarea, statusWrapper } from './reviewTextarea.css';
import { itemTitle, requiredMark } from '../reviewRegisterForm.css';
import { Text } from '@/components/Common';
import { useReviewFormActionContext } from '@/hooks/context';
-const MAX_LENGTH = 200;
+const MIN_LENGTH = 10;
+const MAX_LENGTH = 500;
interface ReviewTextareaProps {
content: string;
@@ -14,11 +16,22 @@ interface ReviewTextareaProps {
const ReviewTextarea = ({ content }: ReviewTextareaProps) => {
const { handleReviewFormValue } = useReviewFormActionContext();
+ const [isTouched, setIsTouched] = useState(false);
const handleReviewText: ChangeEventHandler = (event) => {
handleReviewFormValue({ target: 'content', value: event.currentTarget.value });
};
+ const handleFocus: FocusEventHandler = () => {
+ setIsTouched(false);
+ };
+
+ const handleBlur: FocusEventHandler = () => {
+ setIsTouched(true);
+ };
+
+ const isValid = content.trim().length >= MIN_LENGTH || !isTouched;
+
return (
@@ -27,19 +40,27 @@ const ReviewTextarea = ({ content }: ReviewTextareaProps) => {
*
+
{content.length}/{MAX_LENGTH}
+
+
+ 다른 사람들을 위해 {MIN_LENGTH}자 이상의 리뷰를 작성해보는 건 어떨까요?
+
);
};
diff --git a/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts b/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts
index 38119353..989bc1de 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts
+++ b/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts
@@ -1,5 +1,5 @@
import { vars } from '@/styles/theme.css';
-import { style } from '@vanilla-extract/css';
+import { style, styleVariants } from '@vanilla-extract/css';
export const container = style({
position: 'relative',
@@ -9,8 +9,9 @@ export const reviewTextarea = style({
width: '100%',
padding: '12px 16px',
fontSize: '1.2rem',
- backgroundColor: vars.colors.background.category,
+ backgroundColor: vars.colors.border.light,
border: 'none',
+ borderRadius: 6,
resize: 'vertical',
selectors: {
@@ -19,12 +20,16 @@ export const reviewTextarea = style({
fontWeight: 500,
color: vars.colors.gray3,
},
+
+ '&:invalid': {
+ border: `1px solid ${vars.colors.error}`,
+ },
},
});
export const statusWrapper = style({
position: 'absolute',
- bottom: 12,
+ bottom: 28,
right: 16,
});
@@ -32,3 +37,12 @@ export const currentLength = style({
color: vars.colors.black,
fontWeight: 500,
});
+
+export const errorMessageBase = style({
+ color: vars.colors.error,
+});
+
+export const errorMessage = styleVariants({
+ show: [errorMessageBase, { opacity: 1 }],
+ hidden: [errorMessageBase, { opacity: 0 }],
+});
From bb068d273170f8dd9de9e9e592ca7de2beb4b995 Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 14 Apr 2024 15:01:10 +0200
Subject: [PATCH 26/27] =?UTF-8?q?feat:=20=EC=84=A4=EB=AA=85=20=EC=97=90?=
=?UTF-8?q?=EB=9F=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=B6=94=EA=B0=80=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.storybook/preview-body.html | 15 ++++++++++++++
src/components/Common/Svg/SvgIcon.tsx | 1 +
src/components/Common/Svg/SvgSprite.tsx | 15 ++++++++++++++
.../ReviewTextarea/ReviewTextarea.tsx | 20 ++++++++++++++-----
.../ReviewTextarea/reviewTextarea.css.ts | 16 ++++++++++-----
5 files changed, 57 insertions(+), 10 deletions(-)
diff --git a/.storybook/preview-body.html b/.storybook/preview-body.html
index f7624591..1e8a9755 100644
--- a/.storybook/preview-body.html
+++ b/.storybook/preview-body.html
@@ -378,6 +378,21 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Common/Svg/SvgIcon.tsx b/src/components/Common/Svg/SvgIcon.tsx
index 8aca43fa..4d5c52b7 100644
--- a/src/components/Common/Svg/SvgIcon.tsx
+++ b/src/components/Common/Svg/SvgIcon.tsx
@@ -46,6 +46,7 @@ export const SVG_ICON_VARIANTS = [
'heartFilled',
'close2',
'disk',
+ 'error',
] as const;
export type SvgIconVariant = (typeof SVG_ICON_VARIANTS)[number];
diff --git a/src/components/Common/Svg/SvgSprite.tsx b/src/components/Common/Svg/SvgSprite.tsx
index f6fb45fa..a4420561 100644
--- a/src/components/Common/Svg/SvgSprite.tsx
+++ b/src/components/Common/Svg/SvgSprite.tsx
@@ -336,6 +336,21 @@ const SvgSprite = () => {
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx b/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
index ea461768..cde88ef9 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
+++ b/src/components/Review/ReviewRegisterForm/ReviewTextarea/ReviewTextarea.tsx
@@ -1,10 +1,17 @@
import { useState } from 'react';
import type { FocusEventHandler, ChangeEventHandler } from 'react';
-import { container, currentLength, errorMessage, reviewTextarea, statusWrapper } from './reviewTextarea.css';
+import {
+ container,
+ currentLength,
+ errorMessage,
+ errorWrapper,
+ reviewTextarea,
+ statusWrapper,
+} from './reviewTextarea.css';
import { itemTitle, requiredMark } from '../reviewRegisterForm.css';
-import { Text } from '@/components/Common';
+import { SvgIcon, Text } from '@/components/Common';
import { useReviewFormActionContext } from '@/hooks/context';
const MIN_LENGTH = 10;
@@ -58,9 +65,12 @@ const ReviewTextarea = ({ content }: ReviewTextareaProps) => {
-
- 다른 사람들을 위해 {MIN_LENGTH}자 이상의 리뷰를 작성해보는 건 어떨까요?
-
+
+
+
+ 다른 사람들을 위해 {MIN_LENGTH}자 이상의 리뷰를 작성해보는 건 어떨까요?
+
+
);
};
diff --git a/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts b/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts
index 989bc1de..5bba8c5e 100644
--- a/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts
+++ b/src/components/Review/ReviewRegisterForm/ReviewTextarea/reviewTextarea.css.ts
@@ -38,11 +38,17 @@ export const currentLength = style({
fontWeight: 500,
});
-export const errorMessageBase = style({
- color: vars.colors.error,
+export const errorWrapperBase = style({
+ display: 'flex',
+ alignItems: 'center',
+ gap: 4,
+});
+
+export const errorWrapper = styleVariants({
+ show: [errorWrapperBase, { opacity: 1 }],
+ hidden: [errorWrapperBase, { opacity: 0 }],
});
-export const errorMessage = styleVariants({
- show: [errorMessageBase, { opacity: 1 }],
- hidden: [errorMessageBase, { opacity: 0 }],
+export const errorMessage = style({
+ color: vars.colors.error,
});
From 37176a1ecc9865b03eb248f9652557a26b5bb25e Mon Sep 17 00:00:00 2001
From: Leejin-Yang
Date: Sun, 14 Apr 2024 15:04:19 +0200
Subject: [PATCH 27/27] =?UTF-8?q?feat:=20=EB=A6=AC=EB=B7=B0=20=ED=83=9C?=
=?UTF-8?q?=EA=B7=B8=20=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=20=EC=8A=A4?=
=?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ReviewTagSheet/ReviewTagSheet.stories.tsx | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 src/components/Review/ReviewTagSheet/ReviewTagSheet.stories.tsx
diff --git a/src/components/Review/ReviewTagSheet/ReviewTagSheet.stories.tsx b/src/components/Review/ReviewTagSheet/ReviewTagSheet.stories.tsx
new file mode 100644
index 00000000..f42f1bd7
--- /dev/null
+++ b/src/components/Review/ReviewTagSheet/ReviewTagSheet.stories.tsx
@@ -0,0 +1,38 @@
+import { BottomSheet, useBottomSheet } from '@fun-eat/design-system';
+import type { Meta, StoryObj } from '@storybook/react';
+import { useEffect } from 'react';
+
+import ReviewTagSheet from './ReviewTagSheet';
+
+import ReviewFormProvider from '@/contexts/ReviewFormContext';
+
+const meta: Meta = {
+ title: 'common/ReviewTagSheet',
+ component: ReviewTagSheet,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {
+ render: () => {
+ const { isOpen, isClosing, handleOpenBottomSheet, handleCloseBottomSheet } = useBottomSheet();
+
+ useEffect(() => {
+ handleOpenBottomSheet();
+ }, []);
+
+ return (
+
+
+
+ );
+ },
+};