From af6517995cc2c0d1d52a58b5cdd43a24bfaad4b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=80=EC=9B=90?= <143994508+woneeeee@users.noreply.github.com> Date: Tue, 4 Feb 2025 11:54:56 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=88=98=EC=A0=95=20(#111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 프로필 수정 api 연결 * fix: 계좌번호 type 수정 * fix: 계좌번호 input 추가 * fix: rounded 수정 * fix: profileEditVerificationTypes 설정 * fix: 프로필 수정 로직 추가 * feat: 닉네임 수정 스키마 추가 * fix: profileImageUpload FieldValues 추가 * feat: 프로필 수정 api 연결 * remove: 불필요한 주석 삭제 * fix: 채팅방 계좌 설정 * remove: 불필요한 주석 제거 --- src/components/chat/bottomMenu/index.tsx | 13 +++- .../chat/modal/sendAccountModal.tsx | 4 +- src/components/commons/Input.tsx | 2 +- .../ProfileImageUpload.tsx | 14 ++-- src/libs/apis/updateUserProfile.api.ts | 11 +++ src/libs/schemas/auth.ts | 19 +++++ src/pages/mathcing/index.tsx | 78 +++++++++++++++++++ src/pages/my-page/EditProfilePage.tsx | 69 +++++++++++----- src/types/auth.d.ts | 7 ++ 9 files changed, 185 insertions(+), 32 deletions(-) create mode 100644 src/libs/apis/updateUserProfile.api.ts create mode 100644 src/pages/mathcing/index.tsx diff --git a/src/components/chat/bottomMenu/index.tsx b/src/components/chat/bottomMenu/index.tsx index c5ca082..cf30fd6 100644 --- a/src/components/chat/bottomMenu/index.tsx +++ b/src/components/chat/bottomMenu/index.tsx @@ -13,6 +13,7 @@ import useTimerStore from '@/store/useTimerStore'; import { getCloseMatching } from '@/libs/apis/getCloseMatching.api'; import getExitChatRoom from '@/libs/apis/getExitChatRoom'; import useSSEStore from '@/store/useSSEStore'; +import useUserStore from '@/store/useUserStore'; const BottomMenu = ({ onSendAccount, @@ -29,6 +30,8 @@ const BottomMenu = ({ const nav = useNavigate(); const { messages } = useSSEStore(); const [isOwner, setIsOwner] = useState(false); + const { user } = useUserStore(); + const accountNumber = user?.accountNumber || '계좌번호 없음'; messages.forEach((message) => { if (message.topic === 'match_room_created') { @@ -38,6 +41,10 @@ const BottomMenu = ({ }); const handleSendClick = () => { + if (!user?.accountNumber) { + openToast('등록된 계좌번호가 없습니다.', 'error'); + return; + } setShowAccountModal(true); }; @@ -87,7 +94,7 @@ const BottomMenu = ({ }; const clickHandlers: Record void> = { - '계좌 전송': isOwner ? handleSendClick : () => {}, + '계좌 전송': handleSendClick, '택시 호출': isOwner ? handleTaxiClick : () => {}, '매칭 마감': isOwner ? handleCloseMatching : () => {}, '매칭 취소': handleExitModal, @@ -100,7 +107,7 @@ const BottomMenu = ({ key={index} onClick={clickHandlers[item.label] || undefined} className={`${ - !isOwner && item.label !== '매칭 취소' + item.label !== '계좌 전송' && !isOwner && item.label !== '매칭 취소' ? 'cursor-not-allowed opacity-50' : 'cursor-pointer' }`} @@ -112,7 +119,7 @@ const BottomMenu = ({ {showAccountModal && ( setShowAccountModal(false)} - account="농협 302 XXXX XXXX XX" + account={accountNumber} onSend={(accountInfo) => { onSendAccount(accountInfo); setShowAccountModal(false); diff --git a/src/components/chat/modal/sendAccountModal.tsx b/src/components/chat/modal/sendAccountModal.tsx index e7e5c30..4a24026 100644 --- a/src/components/chat/modal/sendAccountModal.tsx +++ b/src/components/chat/modal/sendAccountModal.tsx @@ -14,8 +14,8 @@ const SendAccountModal: React.FC = ({ }) => { return ( -
-

{account}

+
+

{account}

+
+ )} + + ); +}; + +export default MatchingInfoPage; diff --git a/src/pages/my-page/EditProfilePage.tsx b/src/pages/my-page/EditProfilePage.tsx index ed9bc82..acbf613 100644 --- a/src/pages/my-page/EditProfilePage.tsx +++ b/src/pages/my-page/EditProfilePage.tsx @@ -2,22 +2,24 @@ import BackButton from '@/components/commons/BackButton'; import Button from '@/components/commons/Button'; import Input from '@/components/commons/Input'; import { z } from 'zod'; -import { userInfoVerificationSchema } from '@/libs/schemas/auth'; -import { UserInfoVerificationTypes } from 'gachTaxi-types'; +import { profileEditVerificationSchema } from '@/libs/schemas/auth'; +import { ProfileEditVerificationTypes } from 'gachTaxi-types'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm, SubmitHandler } from 'react-hook-form'; import ProfileImageUpload from '@/components/sign/userInfoVerification/ProfileImageUpload'; import useUploadImage from '@/hooks/useUploadImage'; +import { updateUserProfile } from '@/libs/apis/updateUserProfile.api'; +import { useToast } from '@/contexts/ToastContext'; +import useUserStore from '@/store/useUserStore'; +import handleAxiosError from '@/libs/apis/axiosError.api'; const EditProfilePage = () => { - const profileForm = useForm>({ - resolver: zodResolver(userInfoVerificationSchema), + const profileForm = useForm>({ + resolver: zodResolver(profileEditVerificationSchema), defaultValues: { - nickname: '', - realName: '', - studentNumber: '', - gender: 'MALE', + nickName: '', profilePicture: undefined, + accountNumber: '', }, mode: 'onSubmit', }); @@ -25,16 +27,39 @@ const EditProfilePage = () => { const currentImage = profileForm.watch('profilePicture'); const { imagePreview, uploadedImage, setImagePreview } = useUploadImage(currentImage); + const { setUser } = useUserStore(); + const { openToast } = useToast(); - const handleSubmitChange: SubmitHandler = ( - data, - ) => { + const handleSubmitChange: SubmitHandler< + ProfileEditVerificationTypes + > = async (data) => { try { - console.log(data); - console.log(uploadedImage); - profileForm.setValue('nickname', ''); - } catch (e) { - console.error(e); + const updateData = profileForm.getValues(); + if ( + data.profilePicture !== uploadedImage && + typeof data.profilePicture !== 'string' + ) { + updateData.profilePicture = uploadedImage; + const res = await updateUserProfile(updateData); + if (res?.code === 200) { + const userData = res?.data; + setUser(userData); + openToast(res.message, 'success'); + } + } else { + const res = await updateUserProfile(data); + + if (res?.code === 200) { + if (res?.data) { + const userData = res.data; + setUser(userData); + } + openToast(res.message, 'success'); + } + } + } catch (error) { + const errorMessage = handleAxiosError(error); + openToast(errorMessage, 'error'); } }; @@ -48,7 +73,7 @@ const EditProfilePage = () => { className="flex flex-col gap-2 w-full" onSubmit={profileForm.handleSubmit( handleSubmitChange as SubmitHandler< - z.infer + z.infer >, )} > @@ -60,12 +85,20 @@ const EditProfilePage = () => { + + diff --git a/src/types/auth.d.ts b/src/types/auth.d.ts index c8d003d..b4e0696 100644 --- a/src/types/auth.d.ts +++ b/src/types/auth.d.ts @@ -31,6 +31,12 @@ declare module 'gachTaxi-types' { gender: 'MALE' | 'FEMALE'; } + interface ProfileEditVerificationTypes { + profilePicture?: file | string | undefined; + nickName?: string; + accountNumber?: string; + } + interface AgreementsTypes { termsAgreement: boolean; privacyAgreement: boolean; @@ -46,6 +52,7 @@ declare module 'gachTaxi-types' { email: string; role: string; gender: string; + accountNumber?: string; } // 회원가입 또는 로그인 시 반환되는 유저 정보