Skip to content

Commit 19342d2

Browse files
authored
Merge pull request #44 from SOPT-all/feat/review-component/#26
[feat/#26] 사용자 후기 컴포넌트 구현
2 parents 068b55f + b6e05ad commit 19342d2

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { style } from "@vanilla-extract/css";
2+
3+
import { components } from "@/shared/styles/layer.css";
4+
import { color } from "@/shared/styles/tokens/color.css";
5+
import { typographyStyle } from "@/shared/styles/typography.css";
6+
7+
export const reviewCard = style({
8+
"@layer": {
9+
[components]: {
10+
padding: "2rem 0",
11+
backgroundColor: color.white[100],
12+
borderBottom: `0.1rem solid ${color.white[300]}`,
13+
},
14+
},
15+
});
16+
17+
export const reviewHeader = style({
18+
"@layer": {
19+
[components]: {
20+
display: "flex",
21+
alignItems: "flex-start",
22+
columnGap: "1.2rem",
23+
marginBottom: "1.2rem",
24+
},
25+
},
26+
});
27+
28+
export const reviewProfile = style({
29+
"@layer": {
30+
[components]: {
31+
width: "3.4rem",
32+
height: "3.4rem",
33+
borderRadius: "50%",
34+
backgroundColor: color.gray[200],
35+
border: `0.1rem solid ${color.white[300]}`,
36+
},
37+
},
38+
});
39+
40+
export const reviewNickname = style({
41+
"@layer": {
42+
[components]: {
43+
...typographyStyle("body1"),
44+
margin: 0,
45+
marginBottom: "0.4rem",
46+
},
47+
},
48+
});
49+
50+
// 날짜 + 별점
51+
export const reviewMeta = style({
52+
"@layer": {
53+
[components]: {
54+
...typographyStyle("body4"),
55+
color: color.black[200],
56+
display: "flex",
57+
alignItems: "center",
58+
columnGap: "0.4rem",
59+
},
60+
},
61+
});
62+
63+
export const reviewScore = style({
64+
"@layer": {
65+
[components]: {
66+
color: color.gray[100],
67+
display: "inline-flex",
68+
alignItems: "center",
69+
},
70+
},
71+
});
72+
73+
export const reviewStarWrapper = style({
74+
"@layer": {
75+
[components]: {
76+
width: "2.4rem",
77+
height: "2.4rem",
78+
padding: "0.2rem",
79+
boxSizing: "border-box",
80+
display: "flex",
81+
alignItems: "center",
82+
justifyContent: "center",
83+
},
84+
},
85+
});
86+
87+
export const reviewContent = style({
88+
"@layer": {
89+
[components]: {
90+
...typographyStyle("body4"),
91+
margin: 0,
92+
color: color.black[200],
93+
},
94+
},
95+
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { default as Star } from "@svg/star.svg?react";
2+
import * as styles from "./review-card.css";
3+
4+
export interface ReviewCardProps {
5+
nickname: string; // 닉네임
6+
score: number; // 별점
7+
createdAt: string; // 작성일
8+
content: string; // 후기 내용
9+
}
10+
11+
export const ReviewCard = ({
12+
nickname,
13+
score,
14+
createdAt,
15+
content,
16+
}: ReviewCardProps) => {
17+
return (
18+
// 후기 카드 전체
19+
<article className={styles.reviewCard}>
20+
<div className={styles.reviewHeader}>
21+
{/* 왼쪽 프로필 */}
22+
<div className={styles.reviewProfile} />
23+
24+
{/* 오른쪽: 닉네임 + (작성일 / 별점) */}
25+
<div>
26+
<p className={styles.reviewNickname}>{nickname}</p>
27+
<div className={styles.reviewMeta}>
28+
<span>{createdAt}</span>
29+
<span className={styles.reviewScore}>
30+
<span className={styles.reviewStarWrapper}>
31+
<Star />
32+
</span>
33+
{score.toFixed(1)}
34+
</span>
35+
</div>
36+
</div>
37+
</div>
38+
39+
{/* 본문: 후기 내용 */}
40+
<p className={styles.reviewContent}>{content}</p>
41+
</article>
42+
);
43+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { style } from "@vanilla-extract/css";
2+
import { components } from "@/shared/styles/layer.css";
3+
4+
// 후기 리스트 섹션 전체 박스
5+
export const reviewListSection = style({
6+
"@layer": {
7+
[components]: {
8+
padding: "1.2rem 1.6rem 0",
9+
},
10+
},
11+
});
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { ReviewCard, type ReviewCardProps } from "./review-card";
2+
import * as styles from "./review-list.css";
3+
4+
type Review = ReviewCardProps & {
5+
reviewId: number;
6+
};
7+
8+
const mockReviews: Review[] = [
9+
{
10+
reviewId: 1,
11+
nickname: "임지성",
12+
createdAt: "2024.11.25",
13+
score: 4.0,
14+
content:
15+
"여자친구 생일에 특별한 편지를 주고싶어서 찾아보다가 이쁜 카세트로 목소리를 녹음해서 줄수있는게 있길래 한번 구매해봤어요 아직 전달을 하지는 못했지만 사진도 정말 이쁘게 들어가있고 문구와 디자인도 너무 이쁜것 같아요 새로운 감동을 줄 수 있을것 같습니다 대만족이에요!",
16+
},
17+
{
18+
reviewId: 2,
19+
nickname: "오수빈",
20+
createdAt: "2024.11.25",
21+
score: 4.0,
22+
content:
23+
"여자친구 생일에 특별한 편지를 주고싶어서 찾아보다가 이쁜 카세트로 목소리를 녹음해서 줄수있는게 있길래 한번 구매해봤어요 아직 전달을 하지는 못했지만 사진도 정말 이쁘게 들어가있고 문구와 디자인도 너무 이쁜것 같아요 새로운 감동을 줄 수 있을것 같습니다 대만족이에요!",
24+
},
25+
{
26+
reviewId: 3,
27+
nickname: "지민재",
28+
createdAt: "2024.11.25",
29+
score: 4.0,
30+
content:
31+
"여자친구 생일에 특별한 편지를 주고싶어서 찾아보다가 이쁜 카세트로 목소리를 녹음해서 줄수있는게 있길래 한번 구매해봤어요 아직 전달을 하지는 못했지만 사진도 정말 이쁘게 들어가있고 문구와 디자인도 너무 이쁜것 같아요 새로운 감동을 줄 수 있을것 같습니다 대만족이에요!",
32+
},
33+
{
34+
reviewId: 4,
35+
nickname: "배정민",
36+
createdAt: "2024.11.25",
37+
score: 4.0,
38+
content:
39+
"여자친구 생일에 특별한 편지를 주고싶어서 찾아보다가 이쁜 카세트로 목소리를 녹음해서 줄수있는게 있길래 한번 구매해봤어요 아직 전달을 하지는 못했지만 사진도 정말 이쁘게 들어가있고 문구와 디자인도 너무 이쁜것 같아요 새로운 감동을 줄 수 있을것 같습니다 대만족이에요!",
40+
},
41+
{
42+
reviewId: 5,
43+
nickname: "배",
44+
createdAt: "2024.11.25",
45+
score: 4.0,
46+
content:
47+
"여자친구 생일에 특별한 편지를 주고싶어서 찾아보다가 이쁜 카세트로 목소리를 녹음해서 줄수있는게 있길래 한번 구매해봤어요 아직 전달을 하지는 못했지만 사진도 정말 이쁘게 들어가있고 문구와 디자인도 너무 이쁜것 같아요 새로운 감동을 줄 수 있을것 같습니다 대만족이에요!",
48+
},
49+
];
50+
51+
export const ReviewList = () => {
52+
return (
53+
// 후기 리스트 전체를 감싸는 컨테이너
54+
<section className={styles.reviewListSection}>
55+
{mockReviews.map((review) => (
56+
<ReviewCard
57+
key={review.reviewId}
58+
nickname={review.nickname}
59+
createdAt={review.createdAt}
60+
score={review.score}
61+
content={review.content}
62+
/>
63+
))}
64+
</section>
65+
);
66+
};

0 commit comments

Comments
 (0)