From 9032b0948a9a302e255181c9fce4ac2c4741a979 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:28:42 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=ED=94=84=EB=A1=9C=ED=95=84=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C(=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=9C=A0=EC=A7=80)=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=A1=9C=EB=94=A9=20=ED=99=94=EB=A9=B4=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20(#853)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: ImageProp export 및 jsxImportSource 삽입 * feat: Profile 컴포넌트 생성 * feat: 상위 컴포넌트로 마진 책임 이동 * feat: 프로필 버튼 클릭 시 마이페이지로 이동하는 기능 구현 * feat: 유저 정보를 불러오는 api 함수 * feat: 카카오로그인 유저일 때 프로필을 보여주도록 기능 추가 * feat: 유저 타입에 isGuest, profileImage 추가 * fix: 스토리북에서 Profile 컴포넌트 뒷 배경 흰 색이 아니도록 설정 * feat: 이벤트 페이지 suspenseQueries를 이용하는 방식으로 변경하여 로딩 중에 빈 화면 대신 화면의 일부를 볼 수 있도록 수정 * style: 사용하지 않는 코드 제거 * feat: size prop을 시멘틱하게 변환하여 small, medium, large로 접근 가능하게 변경 --- client/src/apis/request/user.ts | 11 +++++++ .../Design/components/Image/Image.tsx | 3 +- .../components/Profile/Profile.stories.tsx | 31 +++++++++++++++++++ .../components/Profile/Profile.style.ts | 26 ++++++++++++++++ .../Design/components/Profile/Profile.tsx | 13 ++++++++ .../Design/components/Profile/Profile.type.ts | 7 +++++ client/src/components/Loader/EventLoader.tsx | 8 ++--- .../DesktopShareEventButton.tsx | 10 +++--- .../MobileShareEventButton.tsx | 12 +++---- client/src/constants/queryKeys.ts | 1 + .../queries/user/useRequestGetUserInfo.ts | 16 ++++++++++ client/src/hooks/useEventPageLayout.ts | 3 ++ .../EventPageFallback/EventPageLoading.tsx | 23 ++++++++++++++ .../src/pages/EventPage/EventPageLayout.tsx | 26 ++++++++++++---- client/src/router.tsx | 9 ++++-- client/src/types/serviceType.ts | 2 ++ 16 files changed, 173 insertions(+), 28 deletions(-) create mode 100644 client/src/apis/request/user.ts create mode 100644 client/src/components/Design/components/Profile/Profile.stories.tsx create mode 100644 client/src/components/Design/components/Profile/Profile.style.ts create mode 100644 client/src/components/Design/components/Profile/Profile.tsx create mode 100644 client/src/components/Design/components/Profile/Profile.type.ts create mode 100644 client/src/hooks/queries/user/useRequestGetUserInfo.ts create mode 100644 client/src/pages/EventPage/EventPageFallback/EventPageLoading.tsx diff --git a/client/src/apis/request/user.ts b/client/src/apis/request/user.ts new file mode 100644 index 00000000..c1e2f296 --- /dev/null +++ b/client/src/apis/request/user.ts @@ -0,0 +1,11 @@ +import {User} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {requestGet} from '@apis/fetcher'; + +export const requestGetUserInfo = async () => { + return await requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `/api/users/mine`, + }); +}; diff --git a/client/src/components/Design/components/Image/Image.tsx b/client/src/components/Design/components/Image/Image.tsx index d8a303bc..82a18cfc 100644 --- a/client/src/components/Design/components/Image/Image.tsx +++ b/client/src/components/Design/components/Image/Image.tsx @@ -1,4 +1,5 @@ -type ImageProps = React.ComponentProps<'img'> & { +/** @jsxImportSource @emotion/react */ +export type ImageProps = React.ComponentProps<'img'> & { src: string; fallbackSrc?: string; }; diff --git a/client/src/components/Design/components/Profile/Profile.stories.tsx b/client/src/components/Design/components/Profile/Profile.stories.tsx new file mode 100644 index 00000000..151a50d9 --- /dev/null +++ b/client/src/components/Design/components/Profile/Profile.stories.tsx @@ -0,0 +1,31 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {Profile} from './Profile'; + +const meta: Meta = { + title: 'Components/Profile', + component: Profile, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + decorators: [ + Story => ( +
+ +
+ ), + ], + args: { + src: 'https://wooteco-crew-wiki.s3.ap-northeast-2.amazonaws.com/%EC%9B%A8%EB%94%94%286%EA%B8%B0%29/g583lirp8yg.jpg', + size: 'large', + }, +}; + +export default meta; + +type Story = StoryObj; + +// Playground 스토리 +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/Profile/Profile.style.ts b/client/src/components/Design/components/Profile/Profile.style.ts new file mode 100644 index 00000000..44d67ba4 --- /dev/null +++ b/client/src/components/Design/components/Profile/Profile.style.ts @@ -0,0 +1,26 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@components/Design/theme/theme.type'; + +import {ProfileSize} from './Profile.type'; + +const SEMANTIC_SIZE: Record = { + small: '1rem', + medium: '1.75rem', + large: '3rem', +}; + +export const profileContainerStyle = (theme: Theme, size: ProfileSize) => { + return css({ + display: 'flex', + + width: SEMANTIC_SIZE[size], + height: SEMANTIC_SIZE[size], + + borderRadius: '50%', + + backgroundColor: theme.colors.white, + + objectFit: 'cover', + }); +}; diff --git a/client/src/components/Design/components/Profile/Profile.tsx b/client/src/components/Design/components/Profile/Profile.tsx new file mode 100644 index 00000000..27ec7fb0 --- /dev/null +++ b/client/src/components/Design/components/Profile/Profile.tsx @@ -0,0 +1,13 @@ +/** @jsxImportSource @emotion/react */ +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Image from '../Image/Image'; + +import {profileContainerStyle} from './Profile.style'; +import {ProfileProps} from './Profile.type'; + +export const Profile = ({size = 'medium', ...profileProps}: ProfileProps) => { + const {theme} = useTheme(); + + return ; +}; diff --git a/client/src/components/Design/components/Profile/Profile.type.ts b/client/src/components/Design/components/Profile/Profile.type.ts new file mode 100644 index 00000000..0cabb3e9 --- /dev/null +++ b/client/src/components/Design/components/Profile/Profile.type.ts @@ -0,0 +1,7 @@ +import {ImageProps} from '../Image/Image'; + +export type ProfileSize = 'small' | 'medium' | 'large'; + +export type ProfileProps = ImageProps & { + size?: ProfileSize; +}; diff --git a/client/src/components/Loader/EventLoader.tsx b/client/src/components/Loader/EventLoader.tsx index f4ef9fd0..cb0ed39e 100644 --- a/client/src/components/Loader/EventLoader.tsx +++ b/client/src/components/Loader/EventLoader.tsx @@ -1,4 +1,4 @@ -import {useQueries} from '@tanstack/react-query'; +import {useSuspenseQueries} from '@tanstack/react-query'; import {useEffect} from 'react'; import {requestGetEvent} from '@apis/request/event'; @@ -16,7 +16,7 @@ import QUERY_KEYS from '@constants/queryKeys'; const EventLoader = ({children, ...props}: React.PropsWithChildren = {}) => { const eventId = getEventIdByUrl(); - const queries = useQueries({ + const queries = useSuspenseQueries({ queries: [ {queryKey: [QUERY_KEYS.event], queryFn: () => requestGetEvent({eventId, ...props})}, { @@ -44,9 +44,7 @@ const EventLoader = ({children, ...props}: React.PropsWithChildren query.isLoading === true); - - return !isLoading && children; + return children; }; export default EventLoader; diff --git a/client/src/components/ShareEventButton/DesktopShareEventButton.tsx b/client/src/components/ShareEventButton/DesktopShareEventButton.tsx index c66942f8..e7dd4367 100644 --- a/client/src/components/ShareEventButton/DesktopShareEventButton.tsx +++ b/client/src/components/ShareEventButton/DesktopShareEventButton.tsx @@ -27,12 +27,10 @@ const DesktopShareEventButton = ({onCopy}: DesktopShareEventButtonProps) => { }; return ( -
- - - - -
+ + + + ); }; diff --git a/client/src/components/ShareEventButton/MobileShareEventButton.tsx b/client/src/components/ShareEventButton/MobileShareEventButton.tsx index dd26725d..3cb658e0 100644 --- a/client/src/components/ShareEventButton/MobileShareEventButton.tsx +++ b/client/src/components/ShareEventButton/MobileShareEventButton.tsx @@ -29,13 +29,11 @@ const MobileShareEventButton = ({copyShare, kakaoShare}: MobileShareEventButtonP }; return ( -
- - - - - -
+ + + + + ); }; diff --git a/client/src/constants/queryKeys.ts b/client/src/constants/queryKeys.ts index 044d1a63..e154bef9 100644 --- a/client/src/constants/queryKeys.ts +++ b/client/src/constants/queryKeys.ts @@ -8,6 +8,7 @@ const QUERY_KEYS = { images: 'images', kakaoClientId: 'kakao-client-id', kakaoLogin: 'kakao-login', + userInfo: 'userinfo', }; export default QUERY_KEYS; diff --git a/client/src/hooks/queries/user/useRequestGetUserInfo.ts b/client/src/hooks/queries/user/useRequestGetUserInfo.ts new file mode 100644 index 00000000..5d3b75ec --- /dev/null +++ b/client/src/hooks/queries/user/useRequestGetUserInfo.ts @@ -0,0 +1,16 @@ +import {useSuspenseQuery} from '@tanstack/react-query'; + +import {requestGetUserInfo} from '@apis/request/user'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetUserInfo = () => { + const {data} = useSuspenseQuery({ + queryKey: [QUERY_KEYS.userInfo], + queryFn: requestGetUserInfo, + }); + + return {userInfo: data}; +}; + +export default useRequestGetUserInfo; diff --git a/client/src/hooks/useEventPageLayout.ts b/client/src/hooks/useEventPageLayout.ts index 3c497c25..ef2097b8 100644 --- a/client/src/hooks/useEventPageLayout.ts +++ b/client/src/hooks/useEventPageLayout.ts @@ -6,6 +6,7 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; import useRequestGetEvent from './queries/event/useRequestGetEvent'; import useRequestGetAllMembers from './queries/member/useRequestGetAllMembers'; import useRequestGetSteps from './queries/step/useRequestGetSteps'; +import useRequestGetUserInfo from './queries/user/useRequestGetUserInfo'; const useEventPageLayout = () => { const eventId = getEventIdByUrl(); @@ -14,6 +15,7 @@ const useEventPageLayout = () => { const {totalExpenseAmount} = useTotalExpenseAmountStore(); const {members} = useRequestGetAllMembers(); const {steps} = useRequestGetSteps(); + const {userInfo} = useRequestGetUserInfo(); const billsCount = steps.flatMap(step => [...step.bills]).length; const event = { @@ -21,6 +23,7 @@ const useEventPageLayout = () => { bankName, accountNumber, createdByGuest, + userInfo, }; const eventSummary = { diff --git a/client/src/pages/EventPage/EventPageFallback/EventPageLoading.tsx b/client/src/pages/EventPage/EventPageFallback/EventPageLoading.tsx new file mode 100644 index 00000000..110896f9 --- /dev/null +++ b/client/src/pages/EventPage/EventPageFallback/EventPageLoading.tsx @@ -0,0 +1,23 @@ +import {Flex, Icon, IconButton, MainLayout, TopNav} from '@components/Design'; +import {Footer} from '@components/Footer'; + +const EventPageLoading = () => { + return ( + + + + + + + + + + + + +