11'use client'
22
3+ import Image from 'next/image'
4+
5+ import { useRef , useState } from 'react'
36import { Controller , useForm } from 'react-hook-form'
47
58import { IcProfile , IcProfileCard } from '@/assets/IconList'
69import { positionOptions , techStackOptions } from '@/constants/selectOptions'
10+ import { AffiliationType , UpdateProfileRequest } from '@/types/api/MyPage.types'
711
812import { Button } from '@/components/common/button'
913import { DeletableChip } from '@/components/common/chip'
@@ -13,42 +17,74 @@ import { Text } from '@/components/common/text'
1317import { Form } from '@/components/shared/form'
1418import { Select } from '@/components/shared/select'
1519
16- interface FormValues {
17- name : string
18- nickname : string
19- introduction : string
20- gitHub : string
21- position : string [ ]
22- techStacks : string [ ]
23- affiliation : string
24- }
20+ import { useAuthStore } from '@/stores/useAuthStore'
21+
22+ import { getProfile , updateProfile } from '@/services/mypage'
2523
2624export default function MyPage ( ) : JSX . Element {
27- const methods = useForm < FormValues > ( {
25+ const { user } = useAuthStore ( )
26+
27+ const methods = useForm < UpdateProfileRequest > ( {
2828 mode : 'onChange' ,
2929 defaultValues : {
30- name : '' ,
31- nickname : '' ,
32- introduction : '' ,
33- gitHub : '' ,
34- position : [ ] ,
35- techStacks : [ ] ,
36- affiliation : '' ,
30+ request : {
31+ imageUrl : '' ,
32+ nickname : user ?. nickname ,
33+ introduction : '' ,
34+ gitHub : '' ,
35+ affiliation : 'COMPANY_SCHOOL' ,
36+ } ,
3737 } ,
3838 } )
3939
40- const { control } = methods
41-
42- const onSubmit = ( data : FormValues ) => {
43- console . log ( 'Form Submitted:' , data )
44- }
40+ const { control, watch } = methods
41+ const values = watch ( )
4542
4643 const affiliationOptions = [
4744 { label : '회사 ‧ 학교' , value : 'COMPANY_SCHOOL' } ,
4845 { label : '프리랜서' , value : 'FREELANCER' } ,
4946 { label : '기타' , value : 'OTHER' } ,
5047 ]
5148
49+ const testApiCall = async ( ) => {
50+ try {
51+ const response = await getProfile ( )
52+ console . log ( 'getProfile API 결과:' , response . result )
53+ } catch ( error ) {
54+ console . error ( 'API 호출 에러:' , error )
55+ }
56+ }
57+
58+ const [ preview , setPreview ] = useState < string | null > ( null )
59+ const fileInputRef = useRef < HTMLInputElement > ( null )
60+
61+ const handleFileChange = ( event : React . ChangeEvent < HTMLInputElement > ) => {
62+ const file = event . target . files ?. [ 0 ]
63+ if ( file ) {
64+ const reader = new FileReader ( )
65+ reader . onloadend = ( ) => setPreview ( reader . result as string )
66+ reader . readAsDataURL ( file )
67+ }
68+ }
69+
70+ const handleButtonClick = ( ) => {
71+ fileInputRef . current ?. click ( )
72+ }
73+
74+ const onSubmit = async ( data : UpdateProfileRequest ) => {
75+ if ( ! fileInputRef . current ?. files ?. [ 0 ] ) {
76+ return
77+ }
78+
79+ try {
80+ const profileImage = fileInputRef . current . files [ 0 ] || null
81+ const response = await updateProfile ( data , profileImage )
82+ console . log ( '프로필 업데이트 성공:' , response )
83+ } catch ( error ) {
84+ console . error ( '프로필 업데이트 실패:' , error )
85+ }
86+ }
87+
5288 return (
5389 < div className = 'h-auto max-w-954' >
5490 < Text . Heading as = 'h2' variant = 'heading2' className = 'pb-8 pt-33' >
@@ -58,6 +94,12 @@ export default function MyPage(): JSX.Element {
5894 기본 정보 및 프로필을 설정할 수 있습니다.
5995 </ Text . Body >
6096
97+ < div className = 'mb-20' >
98+ < Button variant = 'contained' onClick = { testApiCall } >
99+ API 테스트
100+ </ Button >
101+ </ div >
102+
61103 < div className = 'w-954 rounded-12 bg-common-white p-40' >
62104 < div className = 'flex flex-row gap-x-20 pb-20' >
63105 < IcProfileCard width = '40' height = '40' />
@@ -87,17 +129,54 @@ export default function MyPage(): JSX.Element {
87129 < Form methods = { methods } onSubmit = { methods . handleSubmit ( onSubmit ) } >
88130 < div className = 'mb-20 flex flex-row gap-x-60' >
89131 < Label labelText = '프로필 사진' className = 'w-146' />
90- < div className = 'flex gap-x-20' >
91- < button >
92- < IcProfile width = '60' height = '60' />
132+ < div className = 'flex items-center gap-x-20' >
133+ < button onClick = { handleButtonClick } >
134+ { preview ? (
135+ < div className = 'h-60 w-60 overflow-hidden rounded-full' >
136+ < Image
137+ src = { preview }
138+ alt = '프로필 이미지'
139+ width = { 60 }
140+ height = { 60 }
141+ className = 'h-full w-full object-cover'
142+ />
143+ </ div >
144+ ) : (
145+ < IcProfile width = '60' height = '60' />
146+ ) }
93147 </ button >
94- < Button variant = 'outlined' > 프로필 변경</ Button >
148+ < Button variant = 'outlined' onClick = { handleButtonClick } >
149+ 프로필 변경
150+ </ Button >
151+ < input
152+ type = 'file'
153+ accept = 'image/*'
154+ ref = { fileInputRef }
155+ className = 'hidden'
156+ onChange = { handleFileChange }
157+ />
95158 </ div >
96159 </ div >
160+
97161 < div className = 'mb-20 flex flex-row gap-x-60' >
98162 < Label labelText = '이름' className = 'w-146' />
99163 < div className = 'w-500' >
100- < Form . Text name = 'name' className = 'h-48' />
164+ < Form . Text
165+ name = 'request.name'
166+ className = 'h-48 text-gray-500'
167+ disabled
168+ />
169+ </ div >
170+ </ div >
171+
172+ < div className = 'mb-20 flex flex-row gap-x-60' >
173+ < Label labelText = '이메일' className = 'w-146' />
174+ < div className = 'w-500' >
175+ < Form . Text
176+ name = 'request.email'
177+ className = 'h-48 text-gray-500'
178+ disabled
179+ />
101180 </ div >
102181 </ div >
103182
@@ -109,14 +188,14 @@ export default function MyPage(): JSX.Element {
109188 < div className = 'mb-20 flex flex-row gap-x-60' >
110189 < Label labelText = '닉네임' className = 'w-146' />
111190 < div className = 'w-500' >
112- < Form . Text name = 'nickname' className = 'h-48' />
191+ < Form . Text name = 'request. nickname' className = 'h-48' />
113192 </ div >
114193 </ div >
115194
116195 < div className = 'mb-20 flex flex-row gap-x-60' >
117196 < Label labelText = '소개' className = 'w-146' />
118197 < div className = 'w-500' >
119- < Form . TextArea size = 'sm' name = 'introduction' fullWidth />
198+ < Form . TextArea size = 'sm' name = 'request. introduction' fullWidth />
120199 </ div >
121200 </ div >
122201
@@ -126,7 +205,7 @@ export default function MyPage(): JSX.Element {
126205 < Text . Body variant = 'body2' color = 'gray500' >
127206 https://github.com/
128207 </ Text . Body >
129- < Form . Text name = 'gitHub' placeholder = '입력' />
208+ < Form . Text name = 'request. gitHub' placeholder = '입력' />
130209 </ div >
131210 </ div >
132211
@@ -141,12 +220,11 @@ export default function MyPage(): JSX.Element {
141220 커리어
142221 </ Text . Heading >
143222
144- < div className = 'mb-20 flex flex-row items-center gap-x-60' >
223+ { /* <div className='mb-20 flex flex-row items-center gap-x-60'>
145224 <Label labelText='포지션' className='h-48 w-146' />
146225 <Controller
147226 name='position'
148227 control={control}
149- rules = { { required : '기술 스택을 선택해주세요.' } }
150228 render={({ field, fieldState: { error } }) => (
151229 <div>
152230 <Select
@@ -193,7 +271,6 @@ export default function MyPage(): JSX.Element {
193271 <Controller
194272 name='techStacks'
195273 control={control}
196- rules = { { required : '기술 스택을 선택해주세요.' } }
197274 render={({ field, fieldState: { error } }) => (
198275 <div>
199276 <Select
@@ -233,12 +310,13 @@ export default function MyPage(): JSX.Element {
233310 </div>
234311 )}
235312 />
236- </ div >
313+ </div> */ }
314+
237315 < div className = 'mb-40 flex gap-x-60' >
238316 < Label labelText = '소속' className = 'w-146' />
239317 < div className = 'flex w-500 gap-x-40' >
240318 < Form . Radio
241- name = 'affiliation'
319+ name = 'request. affiliation'
242320 options = { affiliationOptions }
243321 rules = { { required : '소속을 선택해주세요.' } }
244322 />
@@ -248,9 +326,12 @@ export default function MyPage(): JSX.Element {
248326 < Button size = 'lg' className = 'bg-semantic-negative' >
249327 회원 탈퇴
250328 </ Button >
251- < Button size = 'lg' disabled >
329+ < Button size = 'lg' type = 'submit' >
252330 프로필 저장
253331 </ Button >
332+ < Button size = 'lg' onClick = { ( ) => console . log ( values ) } >
333+ 테스트
334+ </ Button >
254335 </ div >
255336 </ Form >
256337 </ div >
0 commit comments