From 5821747e531bb9b89adbc242d9ed8b50f68c1ef0 Mon Sep 17 00:00:00 2001 From: readygetset Date: Thu, 18 Jan 2024 15:32:41 +0900 Subject: [PATCH 1/2] feat: user profile page --- src/data/messages.ts | 4 +++ src/hooks/api/user/user.ts | 53 +++++++++++++++++++++++++++++++++ src/pages/UserProfile/index.tsx | 50 +++++++++++++++++++++++++++++++ src/route/index.tsx | 2 ++ 4 files changed, 109 insertions(+) create mode 100644 src/hooks/api/user/user.ts create mode 100644 src/pages/UserProfile/index.tsx diff --git a/src/data/messages.ts b/src/data/messages.ts index 36e9eeb..4c2a9d9 100644 --- a/src/data/messages.ts +++ b/src/data/messages.ts @@ -25,3 +25,7 @@ export const APPLY_MESSAGE = { APPLY_REJECT_FAIL: '대여 신청 거절에 문제가 생겼어요 :(', APPLY_CREATE_FAIL: '대여 신청에 문제가 생겼어요 :(', }; +export const USER_MESSAGE = { + USER_CLOTHES_NOT_FOUND: '사용자의 옷을 찾을 수 없어요 :(', + USER_NOT_FOUND: '사용자를 찾을 수 없어요 :(', +}; diff --git a/src/hooks/api/user/user.ts b/src/hooks/api/user/user.ts new file mode 100644 index 0000000..851c592 --- /dev/null +++ b/src/hooks/api/user/user.ts @@ -0,0 +1,53 @@ +import { enqueueSnackbar } from 'notistack'; +import axios, { AxiosError } from 'axios'; + +import { USER_MESSAGE } from '../../../data/messages'; + +export interface UserClothes { + id: number; + closetId?: number; + category?: string; + season?: string; + status: string; + isOpen: boolean; + name: string; + tag?: string; + isWished: boolean; + image?: string /* TODO: 백에서 정의하는 이름에 맞게 변경 */; +} +export async function getUserClothesAPICall(userId: number) { + try { + const response = await axios.get(`${process.env.REACT_APP_API_URL}/clothes/user/${userId}`); + if (response.status === 200) { + return response.data; + } + } catch (err) { + if (err instanceof AxiosError) { + enqueueSnackbar(err.response?.data?.message ?? USER_MESSAGE.USER_CLOTHES_NOT_FOUND, { variant: 'error' }); + } else { + enqueueSnackbar(USER_MESSAGE.USER_CLOTHES_NOT_FOUND, { variant: 'error' }); + } + } + return null; +} +export interface UserProfile { + username?: string; + nickname?: string; + location?: string; + phoneNumber?: string; +} +export async function getUserProfileAPICall(userId: number) { + try { + const response = await axios.get(`${process.env.REACT_APP_API_URL}/user/${userId}`); + if (response.status === 200) { + return response.data; + } + } catch (err) { + if (err instanceof AxiosError) { + enqueueSnackbar(err.response?.data?.message ?? USER_MESSAGE.USER_NOT_FOUND, { variant: 'error' }); + } else { + enqueueSnackbar(USER_MESSAGE.USER_NOT_FOUND, { variant: 'error' }); + } + } + return null; +} diff --git a/src/pages/UserProfile/index.tsx b/src/pages/UserProfile/index.tsx new file mode 100644 index 0000000..3597e37 --- /dev/null +++ b/src/pages/UserProfile/index.tsx @@ -0,0 +1,50 @@ +import { useParams } from 'react-router-dom'; +import { useEffect, useState } from 'react'; +import { Box, Typography } from '@mui/material'; + +import { UserClothes, UserProfile, getUserClothesAPICall, getUserProfileAPICall } from '../../hooks/api/user/user'; +import ClothPreviewCard from '../../components/ClothesPreviewCard'; + +export function UserProfilePage() { + const { id } = useParams(); + const userId = Number(id); + const [clothes, setClothes] = useState(null); + const [profile, setProfile] = useState(null); + const getUserClothes = async () => { + try { + const result = await getUserClothesAPICall(userId); + setClothes(result); + } catch (error) { + // + } + }; + const getUserProfile = async () => { + try { + const result = await getUserProfileAPICall(userId); + setProfile(result); + } catch (error) { + // + } + }; + useEffect(() => { + getUserClothes(); + getUserProfile(); + }, [userId]); + return ( + + {profile?.nickname} + {profile?.location} + {clothes?.map((cloth) => ( + + ))} + + ); +} diff --git a/src/route/index.tsx b/src/route/index.tsx index b241409..332557f 100644 --- a/src/route/index.tsx +++ b/src/route/index.tsx @@ -1,5 +1,6 @@ import { Route, Routes } from 'react-router-dom'; +import { UserProfilePage } from '../pages/UserProfile'; import { RegisterPage } from '../pages/Register'; import { ProfilePage } from '../pages/Profile'; import MyPageWish from '../pages/MyPage/wish'; @@ -26,6 +27,7 @@ export function RouteComponent() { } /> } /> } /> + } /> ); } From 9dd3b70e7580e15c0c5558ea0581f15f8d63c339 Mon Sep 17 00:00:00 2001 From: readygetset Date: Thu, 18 Jan 2024 20:53:14 +0900 Subject: [PATCH 2/2] feat: complete user profile page --- src/pages/UserProfile/index.tsx | 49 +++++++++++++++++++++++---------- src/route/index.tsx | 2 +- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/pages/UserProfile/index.tsx b/src/pages/UserProfile/index.tsx index 3597e37..2726c6c 100644 --- a/src/pages/UserProfile/index.tsx +++ b/src/pages/UserProfile/index.tsx @@ -1,6 +1,6 @@ import { useParams } from 'react-router-dom'; import { useEffect, useState } from 'react'; -import { Box, Typography } from '@mui/material'; +import { Box, Grid, Typography } from '@mui/material'; import { UserClothes, UserProfile, getUserClothesAPICall, getUserProfileAPICall } from '../../hooks/api/user/user'; import ClothPreviewCard from '../../components/ClothesPreviewCard'; @@ -31,20 +31,39 @@ export function UserProfilePage() { getUserProfile(); }, [userId]); return ( - - {profile?.nickname} - {profile?.location} - {clothes?.map((cloth) => ( - - ))} + + + + {profile?.nickname} + + {profile?.location} + + + {clothes?.length ? ( + + + {clothes.map((cloth) => ( + + + + ))} + + + ) : ( + + + 사용자가 보유한 옷이 없어요 + + + )} ); } diff --git a/src/route/index.tsx b/src/route/index.tsx index 332557f..0babf0a 100644 --- a/src/route/index.tsx +++ b/src/route/index.tsx @@ -27,7 +27,7 @@ export function RouteComponent() { } /> } /> } /> - } /> + } /> ); }