11import { Icon } from "@/component/common/Icon" ;
22import { Typography } from "@/component/common/typography" ;
33import { DESIGN_TOKEN_COLOR } from "@/style/designTokens" ;
4- import { Insight } from "@/types/analysis" ;
4+ import { Insight , InsightIconName } from "@/types/analysis" ;
55import { css } from "@emotion/react" ;
66
77type RetrospectsOverviewProps = {
88 description : string ;
9- goodPoints : Insight [ ] ;
10- badPoints : Insight [ ] ;
11- improvementPoints : Insight [ ] ;
9+ goodPoints : Insight [ ] | null ;
10+ badPoints : Insight [ ] | null ;
11+ improvementPoints : Insight [ ] | null ;
1212} ;
1313
14+ type InsightSectionProps = {
15+ title : string ;
16+ data : Insight [ ] | null ;
17+ emptyMessage : string ;
18+ iconName : InsightIconName ;
19+ } ;
20+
21+ type InsightItemProps = {
22+ content : string ;
23+ iconName : InsightIconName ;
24+ } ;
25+
26+ /**
27+ * 잘 하고 있는 점, 부족한 점, 개선이 필요한 점이 없는 경우 표시되는 컴포넌트
28+ *
29+ * @param message 빈 상태 메시지
30+ * @returns
31+ */
32+ const EmptyState = ( { message } : { message : string } ) => (
33+ < div
34+ css = { css `
35+ display : flex;
36+ align-items : center;
37+ justify-content : center;
38+ height : 100% ;
39+ padding : 2rem ;
40+ ` }
41+ >
42+ < Typography variant = "body14Medium" color = "gray500" >
43+ { message }
44+ </ Typography >
45+ </ div >
46+ ) ;
47+
48+ /**
49+ * 인사이트 아이템 컴포넌트
50+ * 잘 하고 있는 점 / 부족한 점 / 개선이 필요한 점 리스트에서 사용
51+ *
52+ * @param content 아이템 내용
53+ * @param iconName 아이콘 이름
54+ * @returns
55+ */
56+ const InsightItem = ( { content, iconName } : InsightItemProps ) => (
57+ < div
58+ css = { css `
59+ display : flex;
60+ align-items : center;
61+ gap : 1.2rem ;
62+ height : 4.4rem ;
63+ padding : 1.2rem 1.6rem ;
64+ background-color : white;
65+ border-radius : 0.8rem ;
66+ ` }
67+ >
68+ < Icon icon = { iconName } size = { 1.6 } />
69+ < Typography variant = "subtitle14Bold" color = "gray800" >
70+ { content }
71+ </ Typography >
72+ </ div >
73+ ) ;
74+
75+ /**
76+ * 인사이트(잘 하고 있는 점, 부족한 점, 개선이 필요한 점) 섹션 컴포넌트
77+ *
78+ * @param title 섹션 제목
79+ * @param data 섹션 데이터
80+ * @param emptyMessage 데이터가 없을 때 표시할 메시지
81+ * @param iconName 아이콘 이름
82+ * @returns
83+ */
84+ const InsightSection = ( { title, data, emptyMessage, iconName } : InsightSectionProps ) => {
85+ const isEmpty = data === null || data . length === 0 ;
86+
87+ return (
88+ < div
89+ css = { css `
90+ display : flex;
91+ flex-direction : column;
92+ gap : 2rem ;
93+ flex : 1 ;
94+ ` }
95+ >
96+ < Typography variant = "title16Bold" color = "gray900" >
97+ { title }
98+ </ Typography >
99+ { isEmpty ? (
100+ < EmptyState message = { emptyMessage } />
101+ ) : (
102+ < div
103+ css = { css `
104+ display : flex;
105+ flex-direction : column;
106+ gap : 0.8rem ;
107+ ` }
108+ >
109+ { data . map ( ( item , index ) => (
110+ < InsightItem key = { index } content = { item . content } iconName = { iconName } />
111+ ) ) }
112+ </ div >
113+ ) }
114+ </ div >
115+ ) ;
116+ } ;
117+
118+ /**
119+ * 회고 개요 컴포넌트
120+ *
121+ * @param description 회고 설명
122+ * @param goodPoints 잘 하고 있는 점
123+ * @param badPoints 부족한 점
124+ * @param improvementPoints 개선이 필요한 점
125+ * @returns
126+ */
14127export default function RetrospectsOverview ( { description, goodPoints, badPoints, improvementPoints } : RetrospectsOverviewProps ) {
15128 return (
16129 < article >
@@ -57,7 +170,6 @@ export default function RetrospectsOverview({ description, goodPoints, badPoints
57170 padding : 2.4rem 2rem ;
58171 ` }
59172 >
60- { /* ---------- 회고 내용 3개 컬럼 ---------- */ }
61173 < div
62174 css = { css `
63175 display : flex;
@@ -66,128 +178,16 @@ export default function RetrospectsOverview({ description, goodPoints, badPoints
66178 height : 100% ;
67179 ` }
68180 >
69- { /* ---------- 잘 하고 있어요 ---------- */ }
70- < div
71- css = { css `
72- display : flex;
73- flex-direction : column;
74- gap : 2rem ;
75- flex : 1 ;
76- ` }
77- >
78- < Typography variant = "title16Bold" color = "gray900" >
79- 잘 하고 있어요
80- </ Typography >
81- < div
82- css = { css `
83- display : flex;
84- flex-direction : column;
85- gap : 0.8rem ;
86- ` }
87- >
88- { goodPoints . map ( ( item , index ) => (
89- < div
90- key = { index }
91- css = { css `
92- display : flex;
93- align-items : center;
94- gap : 1.2rem ;
95- height : 4.4rem ;
96- padding : 1.2rem 1.6rem ;
97- background-color : white;
98- border-radius : 0.8rem ;
99- ` }
100- >
101- < Icon icon = "ic_good_mark" size = { 1.6 } />
102- < Typography variant = "subtitle14Bold" color = "gray800" >
103- { item . content }
104- </ Typography >
105- </ div >
106- ) ) }
107- </ div >
108- </ div >
181+ < InsightSection title = "잘 하고 있어요" data = { goodPoints } emptyMessage = "잘하고 있는 점이 없어요." iconName = "ic_good_mark" />
109182
110- { /* ---------- 이런 점은 부족해요 ---------- */ }
111- < div
112- css = { css `
113- display : flex;
114- flex-direction : column;
115- gap : 2rem ;
116- flex : 1 ;
117- ` }
118- >
119- < Typography variant = "title16Bold" color = "gray900" >
120- 이런 점은 부족해요
121- </ Typography >
122- < div
123- css = { css `
124- display : flex;
125- flex-direction : column;
126- gap : 0.8rem ;
127- ` }
128- >
129- { badPoints . map ( ( item , index ) => (
130- < div
131- key = { index }
132- css = { css `
133- display : flex;
134- align-items : center;
135- gap : 1.2rem ;
136- height : 4.4rem ;
137- padding : 1.2rem 1.6rem ;
138- background-color : white;
139- border-radius : 0.8rem ;
140- ` }
141- >
142- < Icon icon = "ic_bad_mark_red" size = { 1.6 } />
143- < Typography variant = "subtitle14Bold" color = "gray800" >
144- { item . content }
145- </ Typography >
146- </ div >
147- ) ) }
148- </ div >
149- </ div >
183+ < InsightSection title = "이런 점은 부족해요" data = { badPoints } emptyMessage = "부족한 점이 없어요." iconName = "ic_bad_mark_red" />
150184
151- { /* ---------- 개선이 필요해요 ---------- */ }
152- < div
153- css = { css `
154- display : flex;
155- flex-direction : column;
156- gap : 2rem ;
157- flex : 1 ;
158- ` }
159- >
160- < Typography variant = "title16Bold" color = "gray900" >
161- 개선이 필요해요
162- </ Typography >
163- < div
164- css = { css `
165- display : flex;
166- flex-direction : column;
167- gap : 0.8rem ;
168- ` }
169- >
170- { improvementPoints . map ( ( item , index ) => (
171- < div
172- key = { index }
173- css = { css `
174- display : flex;
175- align-items : center;
176- gap : 1.2rem ;
177- height : 4.4rem ;
178- padding : 1.2rem 1.6rem ;
179- background-color : white;
180- border-radius : 0.8rem ;
181- ` }
182- >
183- < Icon icon = "ic_improve_blue_mark" size = { 1.6 } />
184- < Typography variant = "subtitle14Bold" color = "gray800" >
185- { item . content }
186- </ Typography >
187- </ div >
188- ) ) }
189- </ div >
190- </ div >
185+ < InsightSection
186+ title = "개선이 필요해요"
187+ data = { improvementPoints }
188+ emptyMessage = "개선이 필요한 점이 없어요."
189+ iconName = "ic_improve_blue_mark"
190+ />
191191 </ div >
192192 </ section >
193193 </ article >
0 commit comments