1
- import React , { useEffect , useState } from 'react' ;
1
+ import React , { useEffect , useState , useRef } from 'react' ;
2
2
import styled from 'styled-components' ;
3
- import { useDispatch } from 'react-redux' ;
3
+ import { useSelector , useDispatch } from 'react-redux' ;
4
4
import { setRewardCount } from '../../../store/actions/userActions.js' ;
5
5
import { useNavigate } from 'react-router-dom' ;
6
6
import '../../../asset/sass/pages/myPage/infoEditPage.scss' ;
@@ -12,7 +12,6 @@ import { ACCESS_TOKEN } from '../../global/constants';
12
12
import { showErrorToast , showSuccessToast } from '../../ui/toast/toast.tsx' ;
13
13
import { fetchAPI } from '../../global/utils/apiUtil.js' ;
14
14
import Button from '../../ui/button/Button/Button.jsx' ;
15
-
16
15
interface UserData {
17
16
email : string ;
18
17
nickname : string ;
@@ -31,6 +30,13 @@ interface UserResponse {
31
30
statusCode : string ;
32
31
data : UserData ;
33
32
}
33
+ interface UserState {
34
+ rewardCount : number ;
35
+ }
36
+
37
+ interface AppState {
38
+ user : UserState ;
39
+ }
34
40
35
41
const Divider = styled . div `
36
42
height: 1px;
@@ -64,6 +70,7 @@ const ageReverseMapping = {
64
70
} ;
65
71
66
72
function InfoEditPage ( ) {
73
+ const { rewardCount } = useSelector ( ( state : AppState ) => state . user ) ;
67
74
const dispatch = useDispatch ( ) ;
68
75
const navigate = useNavigate ( ) ;
69
76
const [ nickname , setNickname ] = useState ( '' ) ;
@@ -74,6 +81,11 @@ function InfoEditPage() {
74
81
const [ selectedGender , setSelectedGender ] = useState ( '' ) ;
75
82
const [ selectedAge , setSelectedAge ] = useState ( '' ) ;
76
83
84
+ // 팝업 관련
85
+ const [ isShowModal , setIsShowModal ] = useState ( false ) ;
86
+ const [ isShowNicknameModal , setIsShowNicknameModal ] = useState ( false ) ;
87
+ const reportMenuRef = useRef < HTMLDivElement > ( null ) ;
88
+
77
89
const handleSelectTag = ( tag : string ) => setSelectedTag ( tag ) ;
78
90
const handleSelectGender = ( gender : string ) => setSelectedGender ( gender ) ;
79
91
const handleSelectAge = ( age : string ) => setSelectedAge ( age ) ;
@@ -89,6 +101,40 @@ function InfoEditPage() {
89
101
}
90
102
} , [ ] ) ;
91
103
104
+ useEffect ( ( ) => {
105
+ const handleOutsideClick = ( event ) => {
106
+ if (
107
+ reportMenuRef . current &&
108
+ ! reportMenuRef . current . contains ( event . target )
109
+ ) {
110
+ setIsShowModal ( false ) ;
111
+ }
112
+ } ;
113
+
114
+ if ( isShowModal ) {
115
+ window . addEventListener ( 'click' , handleOutsideClick ) ;
116
+ } else {
117
+ window . removeEventListener ( 'click' , handleOutsideClick ) ;
118
+ }
119
+
120
+ return ( ) => {
121
+ window . removeEventListener ( 'click' , handleOutsideClick ) ;
122
+ } ;
123
+ } , [ isShowModal ] ) ;
124
+
125
+
126
+ const toggleReportPopup = ( ) => {
127
+ setIsShowModal ( ( showReport ) => ! showReport ) ;
128
+ setIsShowNicknameModal ( ( showReportModal ) => ! showReportModal ) ;
129
+ } ;
130
+
131
+ const handleOutSideClick = ( event : React . MouseEvent < HTMLDivElement > ) => {
132
+ if ( event ?. target === event ?. currentTarget ) {
133
+ setIsShowNicknameModal ( false ) ;
134
+ }
135
+ } ;
136
+
137
+ // 데이터 불러오기 관련
92
138
const loadUserData = async ( ) => {
93
139
try {
94
140
const data = ( await fetchAPI ( '/api/member/me' , 'GET' ) ) as UserResponse ;
@@ -142,10 +188,20 @@ function InfoEditPage() {
142
188
} ;
143
189
144
190
const handleModifyNickname = async ( ) => {
191
+
145
192
try {
146
- const data = await fetchAPI ( '/api/member/nickname' , 'PATCH' ) ;
147
- setNickname ( data . nickname ) ;
148
- showSuccessToast ( '닉네임이 성공적으로 변경되었습니다.' ) ;
193
+ if ( rewardCount < 20 ) {
194
+ setIsShowNicknameModal ( false )
195
+ showErrorToast ( "붕어빵 갯수가 부족합니다." )
196
+
197
+ } else if ( rewardCount > 20 ) {
198
+ const data = await fetchAPI ( '/api/member/nickname' , 'PATCH' ) ;
199
+ setNickname ( data . nickname ) ;
200
+ showSuccessToast ( '닉네임이 성공적으로 변경되었습니다.' ) ;
201
+ setIsShowNicknameModal ( false )
202
+ loadUserData ( )
203
+ }
204
+
149
205
} catch ( error ) {
150
206
showErrorToast ( '닉네임 변경 중 예상치 못한 오류가 발생했습니다.' ) ;
151
207
}
@@ -159,18 +215,41 @@ function InfoEditPage() {
159
215
) ;
160
216
} ;
161
217
218
+
219
+
162
220
return (
163
221
< StyledPage className = "main-page-container" >
164
222
< StyledHeader >
165
223
< TitleHeader pageTitle = "내 정보 수정" handleGoBack = { handleGoBack } />
166
224
< UserInfoHeader />
225
+
167
226
168
227
< div className = "modify-nick-container" >
228
+ { isShowNicknameModal && (
229
+ < div onClick = { handleOutSideClick } className = "report-popup-overlay" >
230
+ < div className = "nickname-popup" >
231
+ < div className = "nickname-title" > 닉네임을 변경하시겠습니까?</ div >
232
+ < div className = "nickname-sub-title" > 닉네임 변경 시,</ div >
233
+ < div className = "nickname-sub-title" > 붕어빵 20개가 차감됩니다. </ div >
234
+ < div className = "change-nickname-btn" >
235
+ < div
236
+ className = "close-nickname-popup"
237
+ onClick = { ( ) => { setIsShowNicknameModal ( false ) } }
238
+ >
239
+ 아니요
240
+ </ div >
241
+ < div className = "submit-nickname" onClick = { handleModifyNickname } >
242
+ 예
243
+ </ div >
244
+ </ div >
245
+ </ div >
246
+ </ div >
247
+ ) }
169
248
< div className = "modify-info" >
170
249
< span className = "modify-nick" > 닉네임</ span >
171
250
< div className = "modify-nick-info" >
172
251
< span className = "modify-nickname" > { nickname } </ span >
173
- < div className = "modify-nickname-btn" onClick = { handleModifyNickname } >
252
+ < div className = "modify-nickname-btn" onClick = { toggleReportPopup } >
174
253
변경
175
254
</ div >
176
255
</ div >
0 commit comments