diff --git a/src/app/(root)/(routes)/mypage/components/UserInfo.tsx b/src/app/(root)/(routes)/mypage/components/UserInfo.tsx index 4b5c16cd..18720d94 100644 --- a/src/app/(root)/(routes)/mypage/components/UserInfo.tsx +++ b/src/app/(root)/(routes)/mypage/components/UserInfo.tsx @@ -3,33 +3,52 @@ import React, { useState } from 'react' import AvatarEditable from '@/components/domain/avatar-editable' import TextEditable from '@/components/domain/text-editable' -import { useAuth } from '@/contexts/AuthProvider' +import { useToast } from '@/hooks/useToast' +import { postImageFile } from '@/services/images' import { putUserNickname, putUserProfile } from '@/services/user/user' +import { User } from '@/types/user' -const UserInfo = () => { - const { currentUser } = useAuth() +type UserInfoProps = { + user: User +} + +const UserInfo = ({ user }: UserInfoProps) => { + const { toast } = useToast() const [isProfileChanged, setIsProfileChanged] = useState(true) const [isNicknameChanged, setIsNicknameChanged] = useState(true) const fileChangeHandler = async (file: File) => { setIsProfileChanged(true) try { - const _data = await putUserProfile({ file: file }) + const resUpload = await postImageFile(file) + const resProfile = await putUserProfile(resUpload.data) + window.location.reload() + return resProfile.data } catch (error) { setIsProfileChanged(false) console.log(error) - // TODO: toast error message 추가 + toast({ + title: '프로필 이미지 변경 실패', + description: '프로필 이미지 변경에 실패했습니다.', + variant: 'destructive', + }) } } const nicknameChangeHandler = async (nickname: string) => { setIsNicknameChanged(true) try { - const _data = await putUserNickname(nickname) + const res = await putUserNickname(nickname) + window.location.reload() + return res.data } catch (error) { setIsNicknameChanged(false) console.log(error) - //TODO: toast error message 추가 + toast({ + title: '닉네임 변경 실패', + description: '닉네임 변경에 실패했습니다.', + variant: 'destructive', + }) } } @@ -39,12 +58,12 @@ const UserInfo = () => { ) diff --git a/src/app/(root)/(routes)/mypage/page.tsx b/src/app/(root)/(routes)/mypage/page.tsx index cc1cf823..72d67381 100644 --- a/src/app/(root)/(routes)/mypage/page.tsx +++ b/src/app/(root)/(routes)/mypage/page.tsx @@ -1,14 +1,31 @@ import React from 'react' +import PageTitle from '@/components/domain/page-title' +import ApiEndPoint from '@/config/apiEndPoint' +import apiClient from '@/services/apiClient' +import { User } from '@/types/user' +import { getServerCookie } from '@/utils/getServerCookie' import UserInfo from './components/UserInfo' -const MyPage = () => { +const getUserInfo = async (): Promise => { + const token = getServerCookie() + const res = await apiClient.get( + ApiEndPoint.getValidateUser(), + {}, + { + Authorization: `${token}`, + }, + ) + return res.data.userInfo +} + +const MyPage = async () => { + const userInfo = await getUserInfo() + return (
-
-

마이페이지

-
+
- +
{/* TODO: 각 내용에 대한 라우팅 추가 */}
diff --git a/src/components/domain/header/Header.tsx b/src/components/domain/header/Header.tsx index 546da759..0606a4bd 100644 --- a/src/components/domain/header/Header.tsx +++ b/src/components/domain/header/Header.tsx @@ -8,14 +8,10 @@ import AppPath from '@/config/appPath' import Assets from '@/config/assets' import { useAuth } from '@/contexts/AuthProvider' import Logo from '../logo' -import { MenuButton, Avatar } from './components/Avatar' - -// type HeaderProps = { -// isLogin?: boolean -// } +import { MenuButton, AvatarWithDropdown } from './components' const Header = () => { - const { isLoggedIn } = useAuth() + const { isLoggedIn, currentUser } = useAuth() return (
@@ -31,7 +27,7 @@ const Header = () => { alarm {/** TODO: 알림 컴포넌트로 변경 */} - + {/** TODO: 아바타 컴포넌트로 변경 */} ) : ( diff --git a/src/components/domain/header/components/Avatar.tsx b/src/components/domain/header/components/AvatarWithDropdown.tsx similarity index 54% rename from src/components/domain/header/components/Avatar.tsx rename to src/components/domain/header/components/AvatarWithDropdown.tsx index 3cb6f895..fcad532c 100644 --- a/src/components/domain/header/components/Avatar.tsx +++ b/src/components/domain/header/components/AvatarWithDropdown.tsx @@ -1,6 +1,6 @@ import Cookies from 'js-cookie' -import Image from 'next/image' -import Link from 'next/link' +import { useRouter } from 'next/navigation' +import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar' import Button from '@/components/ui/button' import { DropdownMenu, @@ -10,32 +10,13 @@ import { DropdownMenuItem, } from '@/components/ui/dropdown-menu' import AppPath from '@/config/appPath' -import Assets from '@/config/assets' import { Environment } from '@/config/environment' +import { DEFAULT_PROFILE_IMG } from '@/constants/image' import apiClient from '@/services/apiClient' -//TODO: 공용 아바타 컴포넌트로 변경 +const AvatarWithDropdown = ({ imageUrl }: { imageUrl?: string }) => { + const router = useRouter() -const MenuButton = () => { - return ( - - - - - - - - 홈으로 - - - - - ) -} - -const Avatar = () => { const onClickLogout = () => { Cookies.remove(Environment.tokenName()) apiClient.setDefaultHeader('Authorization', '') @@ -45,10 +26,22 @@ const Avatar = () => { return ( - + + { + router.push(AppPath.mypage()) + }} + > + 내 정보 + 로그아웃 @@ -56,4 +49,4 @@ const Avatar = () => { ) } -export { MenuButton, Avatar } +export default AvatarWithDropdown diff --git a/src/components/domain/header/components/MenuButton.tsx b/src/components/domain/header/components/MenuButton.tsx new file mode 100644 index 00000000..eb173b80 --- /dev/null +++ b/src/components/domain/header/components/MenuButton.tsx @@ -0,0 +1,33 @@ +import Image from 'next/image' +import Link from 'next/link' +import Button from '@/components/ui/button' +import { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, +} from '@/components/ui/dropdown-menu' +import AppPath from '@/config/appPath' +import Assets from '@/config/assets' + +const MenuButton = () => { + return ( + + + + + + + + 홈으로 + + + + + ) +} + +export default MenuButton diff --git a/src/components/domain/header/components/index.tsx b/src/components/domain/header/components/index.tsx new file mode 100644 index 00000000..350a14be --- /dev/null +++ b/src/components/domain/header/components/index.tsx @@ -0,0 +1,4 @@ +import AvatarWithDropdown from './AvatarWithDropdown' +import MenuButton from './MenuButton' + +export { AvatarWithDropdown, MenuButton } diff --git a/src/components/domain/image-uploader/ImageUploader.tsx b/src/components/domain/image-uploader/ImageUploader.tsx index 5c0434d0..027f0ae4 100644 --- a/src/components/domain/image-uploader/ImageUploader.tsx +++ b/src/components/domain/image-uploader/ImageUploader.tsx @@ -86,7 +86,9 @@ const ImageUploader = ({ isDeletable={isImageDeletable} isThumbnail={isThumbnail} onDeleteHandler={() => { + console.log(images) setImages(images.filter((_, i) => i !== index)) + onFilesChanged(images.filter((_, i) => i !== index)) }} /> ) diff --git a/src/components/domain/text-editable/TextEditable.tsx b/src/components/domain/text-editable/TextEditable.tsx index e132f92e..4922e0d9 100644 --- a/src/components/domain/text-editable/TextEditable.tsx +++ b/src/components/domain/text-editable/TextEditable.tsx @@ -22,6 +22,7 @@ const TextEditable = ({ const [value, setValue] = useState(defaultText) useEffect(() => { + console.log('이름', defaultText) if (!changedSuccessfully) { setValue(() => defaultText) } diff --git a/src/services/card/card.ts b/src/services/card/card.ts index 7fa03f65..ecf8b69b 100644 --- a/src/services/card/card.ts +++ b/src/services/card/card.ts @@ -83,10 +83,12 @@ export type CardInfoRes = { data: { cardInfo: CardDetail; userInfo: User } } -const getCardInfo = async (cardId: number) => { - const response: CardInfoRes = await apiClient.get( - ApiEndPoint.getCardInfo(cardId), - ) +const getCardInfo = async ( + cardId: number, +): Promise<{ data: { cardInfo: CardDetail; userInfo: User } }> => { + const response = await apiClient.get(ApiEndPoint.getCardInfo(cardId), { + cache: 'no-store', + }) return response } diff --git a/src/services/user/user.ts b/src/services/user/user.ts index 200db439..595f7643 100644 --- a/src/services/user/user.ts +++ b/src/services/user/user.ts @@ -1,19 +1,16 @@ +import { revalidateTag } from 'next/cache' import ApiEndPoint from '@/config/apiEndPoint' import apiClient from '../apiClient' -type putUserProfileReq = { - file: File -} - -const putUserProfile = async ({ file }: putUserProfileReq) => { - const formData = new FormData() - formData.append('profile', file) +const putUserProfile = async (imageUrl: string) => { const response = await apiClient.put( ApiEndPoint.putUserProfile(), - formData, + { + imageUrl, + }, {}, { - 'Content-Type': 'multipart/form-data', + 'Content-Type': 'application/json', }, ) @@ -21,9 +18,16 @@ const putUserProfile = async ({ file }: putUserProfileReq) => { } const putUserNickname = async (nickname: string) => { - const response = await apiClient.put(ApiEndPoint.putUserNickname(), { - nickname, - }) + const response = await apiClient.put( + ApiEndPoint.putUserNickname(), + { + nickname, + }, + {}, + { + 'Content-Type': 'application/json', + }, + ) return response } diff --git a/src/types/user.ts b/src/types/user.ts index e8d50bb2..7106d951 100644 --- a/src/types/user.ts +++ b/src/types/user.ts @@ -2,7 +2,7 @@ interface User { userId: number accountId: string nickname: string - role: 'USER' | 'ADMIN' + role: 'ROLE_USER' | 'ROLE_ADMIN' createdDate: string modifiedDate: string imageUrl?: string