diff --git a/src/@types/auth.types.ts b/src/@types/auth.types.ts index b6e1ac93..6c73fabe 100644 --- a/src/@types/auth.types.ts +++ b/src/@types/auth.types.ts @@ -1,9 +1,10 @@ -import { +import type { FieldErrors, UseFormGetValues, UseFormRegister, UseFormResetField, UseFormSetError, + UseFormSetValue, } from 'react-hook-form'; export interface AuthRequest { @@ -50,3 +51,9 @@ export interface AuthNicknameInputBoxProps extends AuthInputBoxProps { getValues: UseFormGetValues; setError: UseFormSetError; } + +export interface AuthImgProps { + register: UseFormRegister; + inputValue: string; + setValue: UseFormSetValue; +} diff --git a/src/api/member.ts b/src/api/member.ts index dd73f20f..09da9bf5 100644 --- a/src/api/member.ts +++ b/src/api/member.ts @@ -29,10 +29,12 @@ export const putMemberPassword = async (pwDataa: EditPasswordProps) => { }; // 프로필 이미지 업로드 -export const postMember = async (imgData: any) => { - authClient.defaults.headers.post['Content-Type'] = 'multipart/form-data'; - const res = await authClient.post(`member`, imgData); - authClient.defaults.headers.post['Content-Type'] = 'application/json'; +export const postMember = async (formData: FormData) => { + const res = await authClient.post(`member`, formData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }); return res; }; diff --git a/src/assets/images/defaultProfileImg.svg b/src/assets/images/defaultProfileImg.svg deleted file mode 100644 index 39bf316b..00000000 --- a/src/assets/images/defaultProfileImg.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/components/Auth/AuthInput/AuthInputBox/AuthNicknameInputBox.tsx b/src/components/Auth/AuthInput/AuthInputBox/AuthNicknameInputBox.tsx index 0efa08be..e83c28fe 100644 --- a/src/components/Auth/AuthInput/AuthInputBox/AuthNicknameInputBox.tsx +++ b/src/components/Auth/AuthInput/AuthInputBox/AuthNicknameInputBox.tsx @@ -1,6 +1,8 @@ import { getCheckNickname } from '@api/auth'; import { AuthInputWrapper, AuthInput, ErrorMessage } from './AuthInputItem'; import type { AuthNicknameInputBoxProps } from '@/@types/auth.types'; +import { useRecoilValue } from 'recoil'; +import { UserInfoState } from '@recoil/Auth.atom'; const AuthNicknameInputBox = ({ register, @@ -15,8 +17,13 @@ const AuthNicknameInputBox = ({ const nicknameError = errors.nickname; const nicknameErrorMessage = nicknameError?.message; + const userInfo = useRecoilValue(UserInfoState); + const onNicknameBlur = async () => { - if (nicknamePatternValue.test(getValues('nickname'))) { + if ( + nicknamePatternValue.test(getValues('nickname')) && + userInfo?.nickname !== inputValue + ) { try { const res = await getCheckNickname(getValues('nickname')); if (res.status === 200) { diff --git a/src/components/Auth/Login/KakaoLogin.tsx b/src/components/Auth/Login/KakaoLogin.tsx index dfc5dd26..70c5f97c 100644 --- a/src/components/Auth/Login/KakaoLogin.tsx +++ b/src/components/Auth/Login/KakaoLogin.tsx @@ -11,8 +11,6 @@ const KakaoLogin = () => { const [searchParams, _] = useSearchParams(); const nickname = searchParams.get('nickname'); const email = searchParams.get('email'); - const gender = searchParams.get('gender'); - const age_range = searchParams.get('age_range'); const accessToken = searchParams.get('token'); const profile_image = searchParams.get('profile_image'); const signup = searchParams.get('signup'); @@ -24,8 +22,8 @@ const KakaoLogin = () => { nickname: nickname!, email: email!, profileImageUrl: profile_image, - ageType: age_range, - genderType: gender, + ageType: null, + genderType: null, survey: null, }); if (signup === 'true') { diff --git a/src/components/Auth/SignupInfo/AuthDropDown/AuthDropDown.tsx b/src/components/Auth/SignupInfo/AuthDropDown/AuthDropDown.tsx index 94c38aed..0ff87eea 100644 --- a/src/components/Auth/SignupInfo/AuthDropDown/AuthDropDown.tsx +++ b/src/components/Auth/SignupInfo/AuthDropDown/AuthDropDown.tsx @@ -1,17 +1,31 @@ -import { useState } from 'react'; import AuthDropDownOption from './AuthDropDownOption'; import * as Select from '@radix-ui/react-select'; import { DownIcon } from '@components/common/icons/Icons'; +import { UseFormRegister, UseFormSetValue } from 'react-hook-form'; interface Props { label: string; text: string; options: SelectOption[]; + name: string; + register: UseFormRegister; + setValue: UseFormSetValue; + + // initialState: string | null; + // setState: React.Dispatch>; } -const AuthDropDown = ({ label, text, options }: Props) => { - // const [isShow, setIsShow] = useState(false); - const [_, setIsSelected] = useState(text); +const AuthDropDown = ({ + label, + text, + options, + name, + register, + setValue, +}: Props) => { + const onSelectClick = (e: any) => { + setValue(name, e); + }; return ( //
@@ -45,95 +59,32 @@ const AuthDropDown = ({ label, text, options }: Props) => { // )} //
// - - setIsSelected('dd')}> -

{label}

- - - - - - - - - - {options.map((option) => ( - - {option.value} - - ))} - - - -
+
+ +

{label}

+ + + + + + + + + + {options.map((option) => ( + + {option.value} + + ))} + + + +
+
); }; export default AuthDropDown; - -{ - /* - - - - - - - - - - - - - - - Fruits - - Apple - Banana - Blueberry - Grapes - Pineapple - - - - - - - Vegetables - - Aubergine - Broccoli - - Carrot - - Courgette - Leek - - - - - - - Meat - - Beef - Chicken - Lamb - Pork - - - - - - - - */ -} diff --git a/src/components/Auth/SignupInfo/SignupInfoForm.tsx b/src/components/Auth/SignupInfo/SignupInfoForm.tsx index 9ac4f054..8c5732ff 100644 --- a/src/components/Auth/SignupInfo/SignupInfoForm.tsx +++ b/src/components/Auth/SignupInfo/SignupInfoForm.tsx @@ -23,22 +23,28 @@ const SignupInfoForm = () => { mode: 'onChange', criteriaMode: 'all', }); + // const [genderType, setGenderType] = useState(null); + // const [ageType, setAgeType] = useState(null); + const navigate = useNavigate(); const userInfo = useRecoilValue(UserInfoState); useEffect(() => { setValue('nickname', userInfo?.nickname); + setValue('profileImageUrl', userInfo?.profileImageUrl); + setValue('genderType', userInfo?.genderType); + setValue('ageType', userInfo?.ageType); }, [userInfo]); const onInfoSubmit: SubmitHandler = async (data) => { - const { nickname } = data; + const { nickname, profileImageUrl, genderType, ageType } = data; try { const res = await putMember({ nickname: nickname, - profileImageUrl: '', - ageType: null, - genderType: null, + profileImageUrl: profileImageUrl, + genderType: genderType, + ageType: ageType, }); if (res.status === 200) { navigate('/'); @@ -49,10 +55,16 @@ const SignupInfoForm = () => { }; return ( -
+
- +
{ label="성별" text={'성별을 선택해주세요.'} options={genderArr} + name={'genderType'} + register={register} + setValue={setValue} />
@@ -85,15 +103,15 @@ const SignupInfoForm = () => { export default SignupInfoForm; const genderArr: SelectOption[] = [ - { id: '1', value: '여' }, - { id: '2', value: '남' }, - { id: '3', value: '기타' }, + { id: 'FEMALE', value: '여' }, + { id: 'MALE', value: '남' }, + { id: 'NON_BINARY', value: '기타' }, ]; const ageArr: SelectOption[] = [ - { id: '1', value: '10대' }, - { id: '2', value: '20대' }, - { id: '3', value: '30대' }, - { id: '4', value: '40대' }, - { id: '5', value: '50대 이상' }, + { id: 'TEENAGER', value: '10대' }, + { id: 'TWENTIES', value: '20대' }, + { id: 'THIRTIES', value: '30대' }, + { id: 'FOURTIES', value: '40대' }, + { id: 'ABOVE_FIFTIES', value: '50대 이상' }, ]; diff --git a/src/components/Auth/SignupInfo/UserInfoImg.tsx b/src/components/Auth/SignupInfo/UserInfoImg.tsx index 94431846..904fd8b9 100644 --- a/src/components/Auth/SignupInfo/UserInfoImg.tsx +++ b/src/components/Auth/SignupInfo/UserInfoImg.tsx @@ -1,18 +1,24 @@ -import { CameraIcon } from '@components/common/icons/Icons'; +import type { AuthImgProps } from '@/@types/auth.types'; +import { postMember } from '@api/member'; +import { CameraIcon, CloseIcon } from '@components/common/icons/Icons'; -const UserInfoImg = () => { - const onImgChange = (e: React.ChangeEvent) => { - console.log(e); - - // let fileArr = e.target.files; - // setPostImg(Array.from(fileArr)); - - // let fileRead = new FileReader(); - // fileRead.onload = function(){ - // setPreviewImg(fileRead.result); - // }; +const UserInfoImg = ({ register, setValue, inputValue }: AuthImgProps) => { + const onImgChange = async (e: React.ChangeEvent) => { + try { + const formData = new FormData(); + formData.append('images', (e.target.files as FileList)[0]); + const res = await postMember(formData); + if (res.data.status === 200) { + setValue('profileImageUrl', res.data.data.imageUrl); + } + } catch (err) { + console.error(err); + } + }; - // fileRead.readAsDataURL(file[0]); + const onRemoveClick = (e: React.MouseEvent) => { + e.stopPropagation(); + setValue('profileImageUrl', null); }; return (
@@ -21,11 +27,22 @@ const UserInfoImg = () => { className="relative mx-auto flex h-20 w-20 cursor-pointer justify-center overflow-hidden"> -
+ {inputValue && ( + + )} +
-
{ accept="image/*" onChange={onImgChange} /> +
); }; diff --git a/src/components/Mypage/DeleteMemberButton.tsx b/src/components/Mypage/DeleteMemberButton.tsx index 8313f23b..ca73c422 100644 --- a/src/components/Mypage/DeleteMemberButton.tsx +++ b/src/components/Mypage/DeleteMemberButton.tsx @@ -18,7 +18,7 @@ const DeleteMemberButton = () => { alert('회원 탈퇴되었습니다. 감사합니다.'); } } catch (err) { - console.log(err); + console.error(err); } }; @@ -31,7 +31,7 @@ const DeleteMemberButton = () => { message="정말 탈퇴하시겠어요?" onConfirm={handleConfirm} onCancel={handleCancel}> - + ); }; diff --git a/src/components/Mypage/LogoutButton.tsx b/src/components/Mypage/LogoutButton.tsx index 5a5fd2c4..0e6666d7 100644 --- a/src/components/Mypage/LogoutButton.tsx +++ b/src/components/Mypage/LogoutButton.tsx @@ -9,7 +9,7 @@ const LogoutButton = () => { const navigate = useNavigate(); const setUserInfo = useSetRecoilState(UserInfoState); - const onLogoutClick = async (e: any) => { + const onLogoutClick = async (e: React.MouseEvent) => { e.stopPropagation(); }; diff --git a/src/components/Mypage/MypageInfo.tsx b/src/components/Mypage/MypageInfo.tsx index f3001824..b18ae669 100644 --- a/src/components/Mypage/MypageInfo.tsx +++ b/src/components/Mypage/MypageInfo.tsx @@ -22,7 +22,7 @@ const MypageInfo = () => { src={ userInfo?.profileImageUrl ? userInfo.profileImageUrl - : 'http://k.kakaocdn.net/dn/1G9kp/btsAot8liOn/8CWudi3uy07rvFNUkk3ER0/img_110x110.jpg' + : 'https://elasticbeanstalk-ap-northeast-2-077853585725.s3.ap-northeast-2.amazonaws.com/static/387fde04-f7d4-443d-88e1-b678ab5e079ddefaultProfileImg.svg' } />
diff --git a/src/components/Mypage/UserInfoForm.tsx b/src/components/Mypage/UserInfoForm.tsx index cb32de66..2925a017 100644 --- a/src/components/Mypage/UserInfoForm.tsx +++ b/src/components/Mypage/UserInfoForm.tsx @@ -28,15 +28,16 @@ const UserInfoForm = () => { const userInfo = useRecoilValue(UserInfoState); useEffect(() => { setValue('nickname', userInfo?.nickname); + setValue('profileImageUrl', userInfo?.profileImageUrl); }, [userInfo]); const onInfoSubmit: SubmitHandler = async (data) => { - const { nickname } = data; + const { nickname, profileImageUrl } = data; try { const res = await putMember({ nickname: nickname, - profileImageUrl: '', + profileImageUrl: profileImageUrl, ageType: null, genderType: null, }); @@ -49,14 +50,20 @@ const UserInfoForm = () => { }; return ( - +
-
- +
+
- email + {userInfo?.email}
비밀번호 변경 @@ -75,11 +82,17 @@ const UserInfoForm = () => { label="성별" text={'성별을 선택해주세요.'} options={genderArr} + name={'genderType'} + register={register} + setValue={setValue} />
diff --git a/src/pages/mypage/editPassword.page.tsx b/src/pages/mypage/editPassword.page.tsx index a15f89e6..06c276ed 100644 --- a/src/pages/mypage/editPassword.page.tsx +++ b/src/pages/mypage/editPassword.page.tsx @@ -9,7 +9,7 @@ const EditPassword = () => { { - navigate('/mypage'); + navigate('/mypage/info'); }}> 비밀번호 변경 diff --git a/src/pages/signup/signupInfo.page.tsx b/src/pages/signup/signupInfo.page.tsx index b5d89a8a..1482ef3a 100644 --- a/src/pages/signup/signupInfo.page.tsx +++ b/src/pages/signup/signupInfo.page.tsx @@ -1,13 +1,14 @@ import { AuthTitle } from '@components/Auth'; import SignupInfoForm from '@components/Auth/SignupInfo/SignupInfoForm'; import { BackBox } from '@components/common'; +import { ProgressBarIcon } from '@components/common/icons/Icons'; import { useNavigate } from 'react-router-dom'; const SignupInfo = () => { const navigate = useNavigate(); return ( -
+
{ @@ -18,6 +19,9 @@ const SignupInfo = () => { navigate('/'); }} /> +
+ +