33import { useForm , FormProvider } from 'react-hook-form' ;
44import { zodResolver } from '@hookform/resolvers/zod' ;
55import { profileFormSchema , ProfileFormValues } from '@/schemas/profile' ;
6+ import { useState } from 'react' ;
67
78import { GenderRadio } from './GenderRadio' ;
89import { AgeInput } from './AgeInput' ;
@@ -13,8 +14,19 @@ import ConsentConfirm from './ConsentConfirm';
1314import { PERSONAL_INFORMATION_AGREEMENT } from '@/constants/PERSONAL_INFORMATION_AGREEMENT' ;
1415import { Button } from '@/components/ui/button' ;
1516import { PencilLine } from 'lucide-react' ;
17+ import { toast } from 'sonner' ;
18+
19+ import { updateUserData , GenderEnum , ProfileRequest } from '@/apis/profile' ;
20+
21+ type Props = {
22+ id : string ;
23+ email : string ;
24+ } ;
25+
26+ export default function ProfileModal ( { email, id } : Props ) {
27+ const [ error , setError ] = useState < string | null > ( null ) ;
28+ const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
1629
17- export default function ProfileModal ( ) {
1830 const form = useForm < ProfileFormValues > ( {
1931 resolver : zodResolver ( profileFormSchema ) ,
2032 defaultValues : {
@@ -25,19 +37,50 @@ export default function ProfileModal() {
2537 } ,
2638 } ) ;
2739
28- const onSubmit = form . handleSubmit ( ( data ) => {
29- console . log ( '제출 데이터:' , data ) ;
30- alert ( '제출 완료!' ) ;
40+ const saveProfile = async ( data : Omit < ProfileRequest , 'id' > , userId : string ) : Promise < void > => {
41+ try {
42+ setError ( null ) ;
43+ setIsSubmitting ( true ) ;
44+ await updateUserData ( userId , data . sex , data . age , data . job ) ;
45+ toast . success ( '프로필이 저장되었어요!' ) ;
46+ } catch ( err ) {
47+ const message = err instanceof Error ? err . message : '프로필 저장 실패' ;
48+ setError ( message ) ;
49+ toast . error ( message ) ;
50+ throw err ;
51+ } finally {
52+ setIsSubmitting ( false ) ;
53+ }
54+ } ;
55+
56+ const onSubmit = form . handleSubmit ( async ( data ) => {
57+ try {
58+ const ageValue = Number ( data . age ) ;
59+ if ( isNaN ( ageValue ) || ageValue <= 0 ) {
60+ throw new Error ( '나이는 숫자로 입력해주세요.' ) ;
61+ }
62+ await saveProfile (
63+ {
64+ sex : data . gender ,
65+ age : Number ( data . age ) ,
66+ job : data . job ,
67+ } ,
68+ id
69+ ) ;
70+ toast . success ( '프로필이 저장되었어요!' ) ;
71+ } catch ( e ) {
72+ console . error ( e ) ;
73+ }
3174 } ) ;
3275
33- const isSubmitDisabled = Object . keys ( form . formState . errors ) . length > 0 ;
76+ const isSubmitDisabled = isSubmitting || Object . keys ( form . formState . errors ) . length > 0 ;
3477
3578 return (
3679 < FormProvider { ...form } >
3780 < form onSubmit = { onSubmit } >
3881 < div className = "p-4 space-y-3" >
3982 < h2 className = "text-lg text-secondary font-semibold" > 아이디</ h2 >
40- < p className = "text-sm text-secondary mb-3" > user0408 </ p >
83+ < p className = "text-sm text-secondary mb-3" > { email } </ p >
4184
4285 < GenderRadio />
4386 < AgeInput />
@@ -56,7 +99,7 @@ export default function ProfileModal() {
5699 className = "bg-transparent hover:text-primary transition-colors duration-200 cursor-pointer shadow-none border-none px-0 py-0 h-auto disabled:cursor-not-allowed"
57100 >
58101 < span className = "flex items-center gap-1" >
59- < PencilLine size = { 16 } /> 완료
102+ < PencilLine size = { 16 } /> { isSubmitting ? '저장 중...' : '완료' }
60103 </ span >
61104 </ Button >
62105 </ div >
0 commit comments