Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.1.1 #429

Merged
merged 13 commits into from
Oct 17, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[FE] issue419: 스터디 방 페이지 전체 공개 (#427)
* feat: user role, user info api 수정

* feat: 로그인 관련 훅 수정

- useAuth
- useUserInfo
- useUserRole

enabled 옵션 변경

* feat: 로그인 관련 훅 사용하고 있는 컴포넌트 수정

* refactor: type과 상대경로 수정
nan-noo authored Oct 16, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 241a9a4d52b9367f1f0c7952088714a485080bec
17 changes: 13 additions & 4 deletions frontend/src/api/member/index.ts
Original file line number Diff line number Diff line change
@@ -26,6 +26,17 @@ export type ApiUserRole = {
export type ApiUserInformation = {
get: {
responseData: Member;
variables: {
options?: Omit<
UseQueryOptions<
ApiUserInformation['get']['responseData'],
AxiosError,
ApiUserInformation['get']['responseData'],
QueryKey
>,
'queryKey' | 'queryFn'
>;
};
};
};

@@ -48,7 +59,5 @@ export const getUserInformation = async () => {
return checkUserInformation(response.data);
};

export const useGetUserInformation = () =>
useQuery<ApiUserInformation['get']['responseData'], AxiosError>('user-info', getUserInformation, {
enabled: false,
});
export const useGetUserInformation = ({ options }: ApiUserInformation['get']['variables']) =>
useQuery<ApiUserInformation['get']['responseData'], AxiosError>('user-info', getUserInformation, options);
2 changes: 1 addition & 1 deletion frontend/src/components/button-group/ButtonGroup.style.tsx
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ import styled from '@emotion/styled';

import type { MakeRequired } from '@custom-types';

import { ButtonGroupProps } from './ButtonGroup';
import { type ButtonGroupProps } from '@components/button-group/ButtonGroup';

type StyledButtonGroupProps = MakeRequired<
Pick<ButtonGroupProps, 'orientation' | 'gap' | 'height' | 'width' | 'justifyContent' | 'alignItems'>,
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ import styled from '@emotion/styled';

import type { MakeRequired } from '@custom-types';

import { IconButtonProps } from './IconButton';
import { type IconButtonProps } from '@components/button/icon-button/IconButton';

type StyledIconButtonProps = MakeRequired<
Pick<IconButtonProps, 'variant' | 'height' | 'width' | 'fontSize'>,
2 changes: 1 addition & 1 deletion frontend/src/components/flex/Flex.style.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { css } from '@emotion/react';
import styled from '@emotion/styled';

import { FlexProps } from './Flex';
import { type FlexProps } from '@components/flex/Flex';

type StyledFlexProps = Omit<FlexProps, 'children'>;

2 changes: 1 addition & 1 deletion frontend/src/components/wrapper/Wrapper.style.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { css } from '@emotion/react';
import styled from '@emotion/styled';

import { WrapperProps } from './Wrapper';
import { type WrapperProps } from '@components/wrapper/Wrapper';

type StyledWrapperProps = Required<Pick<WrapperProps, 'space'>>;

9 changes: 1 addition & 8 deletions frontend/src/context/login/LoginProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { ReactNode, createContext, useEffect, useState } from 'react';
import { ReactNode, createContext, useState } from 'react';

import { noop } from '@utils';

import AccessTokenController from '@auth/accessTokenController';

import { useUserInfo } from '@hooks/useUserInfo';

type LoginProviderProps = {
children: ReactNode;
};
@@ -23,11 +21,6 @@ export const LoginContext = createContext<ContextType>({
export const LoginProvider = ({ children }: LoginProviderProps) => {
const { hasAccessToken, hasTokenDateTime } = AccessTokenController;
const [isLoggedIn, setIsLoggedIn] = useState(hasAccessToken && hasTokenDateTime);
const { fetchUserInfo } = useUserInfo();

useEffect(() => {
if (isLoggedIn) fetchUserInfo();
}, []);

return <LoginContext.Provider value={{ isLoggedIn, setIsLoggedIn }}>{children}</LoginContext.Provider>;
};
4 changes: 0 additions & 4 deletions frontend/src/hooks/useAuth.ts
Original file line number Diff line number Diff line change
@@ -2,18 +2,14 @@ import { useContext } from 'react';

import AccessTokenController from '@auth/accessTokenController';

import { useUserInfo } from '@hooks/useUserInfo';

import { LoginContext } from '@context/login/LoginProvider';

export const useAuth = () => {
const { isLoggedIn, setIsLoggedIn } = useContext(LoginContext);
const { fetchUserInfo } = useUserInfo();

const login = (accesssToken: string, expiredTime: number) => {
AccessTokenController.save(accesssToken, expiredTime);
setIsLoggedIn(true);
fetchUserInfo();
};

const logout = () => {
16 changes: 15 additions & 1 deletion frontend/src/hooks/useUserInfo.ts
Original file line number Diff line number Diff line change
@@ -2,11 +2,25 @@ import { useContext, useEffect } from 'react';

import { useGetUserInformation } from '@api/member';

import { useAuth } from '@hooks/useAuth';

import { UserInfoContext } from '@context/userInfo/UserInfoProvider';

export const useUserInfo = () => {
const { userInfo, setUserInfo } = useContext(UserInfoContext);
const { data, refetch: fetchUserInfo, isError, isSuccess } = useGetUserInformation();

const { isLoggedIn } = useAuth();

const {
data,
refetch: fetchUserInfo,
isError,
isSuccess,
} = useGetUserInformation({
options: {
enabled: isLoggedIn,
},
});

useEffect(() => {
if (!data || isError || !isSuccess) return;
23 changes: 20 additions & 3 deletions frontend/src/hooks/useUserRole.ts
Original file line number Diff line number Diff line change
@@ -2,13 +2,30 @@ import { useContext, useEffect } from 'react';

import { USER_ROLE } from '@constants';

import { type ApiUserRole, useGetUserRole } from '@api/member';
import { StudyId } from '@custom-types';

import { useGetUserRole } from '@api/member';

import { useAuth } from '@hooks/useAuth';

import { UserRoleContext } from '@context/userRole/UserRoleProvider';

export const useUserRole = ({ studyId, options }: ApiUserRole['get']['variables']) => {
export const useUserRole = ({ studyId }: { studyId: StudyId }) => {
const { userRole, setUserRole } = useContext(UserRoleContext);
const { data, refetch: fetchUserRole, isError, isSuccess } = useGetUserRole({ studyId, options });

const { isLoggedIn } = useAuth();

const {
data,
refetch: fetchUserRole,
isError,
isSuccess,
} = useGetUserRole({
studyId,
options: {
enabled: isLoggedIn,
},
});

useEffect(() => {
if (!data || isError || !isSuccess) return;
7 changes: 1 addition & 6 deletions frontend/src/pages/detail-page/hooks/useDetailPage.ts
Original file line number Diff line number Diff line change
@@ -15,12 +15,7 @@ const useDetailPage = () => {
const detailQueryResult = useGetStudy({ studyId });

const { mutate } = usePostMyStudy();
const { isOwner, isOwnerOrMember, fetchUserRole } = useUserRole({
studyId,
options: {
enabled: isLoggedIn,
},
});
const { isOwner, isOwnerOrMember, fetchUserRole } = useUserRole({ studyId });

const handleRegisterButtonClick = () => {
if (!isLoggedIn) {
Original file line number Diff line number Diff line change
@@ -7,7 +7,8 @@ import { changeDateSeperator } from '@utils';
import tw from '@utils/tw';

import { useDeleteCommunityArticle, useGetCommunityArticle } from '@api/community';
import { useGetUserInformation } from '@api/member';

import { useUserInfo } from '@hooks/useUserInfo';

import { BoxButton } from '@components/button';
import ButtonGroup from '@components/button-group/ButtonGroup';
@@ -24,7 +25,7 @@ export type ArticleProps = {

const Article: FC<ArticleProps> = ({ studyId, articleId }) => {
const { isFetching, isSuccess, isError, data } = useGetCommunityArticle({ studyId, articleId });
const getUserInformationQueryResult = useGetUserInformation();
const { userInfo } = useUserInfo();

const { mutateAsync } = useDeleteCommunityArticle();
const navigate = useNavigate();
@@ -44,31 +45,6 @@ const Article: FC<ArticleProps> = ({ studyId, articleId }) => {
);
};

const renderModifierButtons = () => {
if (!getUserInformationQueryResult.isSuccess || getUserInformationQueryResult.isError) return;
if (!data?.author.username) return;
if (data.author.username !== getUserInformationQueryResult.data.username) return;

return (
<ButtonGroup gap="8px" width="fit-content">
<Link to="edit" relative="path">
<BoxButton type="button" padding="4px 8px" fluid={false}>
글수정
</BoxButton>
</Link>
<BoxButton
type="button"
padding="4px 8px"
fluid={false}
variant="secondary"
onClick={handleDeleteArticleButtonClick}
>
글삭제
</BoxButton>
</ButtonGroup>
);
};

const render = () => {
if (isFetching) {
return <div>Loading...</div>;
@@ -79,14 +55,33 @@ const Article: FC<ArticleProps> = ({ studyId, articleId }) => {

if (isSuccess) {
const { title, author, content, createdDate } = data;
const isMyArticle = author.id === userInfo.id;

return (
<article>
<Flex justifyContent="space-between" gap="16px">
<UserInfoItem src={author.imageUrl} name={author.username} size="md">
<UserInfoItem.Heading>{author.username}</UserInfoItem.Heading>
<UserInfoItem.Content>{changeDateSeperator(createdDate)}</UserInfoItem.Content>
</UserInfoItem>
{renderModifierButtons()}
{isMyArticle && (
<ButtonGroup gap="8px" width="fit-content">
<Link to="edit" relative="path">
<BoxButton type="button" padding="4px 8px" fluid={false}>
글수정
</BoxButton>
</Link>
<BoxButton
type="button"
padding="4px 8px"
fluid={false}
variant="secondary"
onClick={handleDeleteArticleButtonClick}
>
글삭제
</BoxButton>
</ButtonGroup>
)}
</Flex>
<Divider />
<PageTitle>{title}</PageTitle>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useState } from 'react';
import { useParams } from 'react-router-dom';

import { useGetInfiniteLinks } from '@api/links';
@@ -10,17 +10,13 @@ export const useLinkRoomTabPanel = () => {
const { studyId: _studyId } = useParams<{ studyId: string }>();
const studyId = Number(_studyId);

const { fetchUserInfo, userInfo } = useUserInfo();
const { userInfo } = useUserInfo();
const { isOwnerOrMember } = useUserRole({ studyId });

const infiniteLinksQueryResult = useGetInfiniteLinks({ studyId });

const [isModalOpen, setIsModalOpen] = useState(false);

useEffect(() => {
fetchUserInfo();
}, []);

const handleLinkAddButtonClick = () => setIsModalOpen(prev => !prev);
const handleModalClose = () => setIsModalOpen(false);

Original file line number Diff line number Diff line change
@@ -5,9 +5,10 @@ import { PATH } from '@constants';
import { changeDateSeperator } from '@utils';
import tw from '@utils/tw';

import { useGetUserInformation } from '@api/member';
import { useDeleteNoticeArticle, useGetNoticeArticle } from '@api/notice';

import { useUserInfo } from '@hooks/useUserInfo';

import { BoxButton } from '@components/button';
import ButtonGroup from '@components/button-group/ButtonGroup';
import Divider from '@components/divider/Divider';
@@ -23,7 +24,7 @@ export type ArticleProps = {

const Article: React.FC<ArticleProps> = ({ studyId, articleId }) => {
const { isFetching, isSuccess, isError, data } = useGetNoticeArticle({ studyId, articleId });
const getUserInformationQueryResult = useGetUserInformation();
const { userInfo } = useUserInfo();

const { mutateAsync } = useDeleteNoticeArticle();
const navigate = useNavigate();
@@ -43,31 +44,6 @@ const Article: React.FC<ArticleProps> = ({ studyId, articleId }) => {
);
};

const renderModifierButtons = () => {
if (!getUserInformationQueryResult.isSuccess || getUserInformationQueryResult.isError) return;
if (!data?.author.username) return;
if (data.author.username !== getUserInformationQueryResult.data.username) return;

return (
<ButtonGroup gap="8px" width="fit-content">
<Link to="edit" relative="path">
<BoxButton type="button" padding="4px 8px" fluid={false}>
글수정
</BoxButton>
</Link>
<BoxButton
type="button"
padding="4px 8px"
fluid={false}
variant="secondary"
onClick={handleDeleteArticleButtonClick}
>
글삭제
</BoxButton>
</ButtonGroup>
);
};

const render = () => {
if (isFetching) {
return <div>Loading...</div>;
@@ -78,14 +54,33 @@ const Article: React.FC<ArticleProps> = ({ studyId, articleId }) => {

if (isSuccess) {
const { title, author, content, createdDate } = data;
const isMyArticle = author.id === userInfo.id;

return (
<article>
<Flex justifyContent="space-between" gap="16px">
<UserInfoItem src={author.imageUrl} name={author.username} size="md">
<UserInfoItem.Heading>{author.username}</UserInfoItem.Heading>
<UserInfoItem.Content>{changeDateSeperator(createdDate)}</UserInfoItem.Content>
</UserInfoItem>
{renderModifierButtons()}
{isMyArticle && (
<ButtonGroup gap="8px" width="fit-content">
<Link to="edit" relative="path">
<BoxButton type="button" padding="4px 8px" fluid={false}>
글수정
</BoxButton>
</Link>
<BoxButton
type="button"
padding="4px 8px"
fluid={false}
variant="secondary"
onClick={handleDeleteArticleButtonClick}
>
글삭제
</BoxButton>
</ButtonGroup>
)}
</Flex>
<Divider />
<PageTitle>{title}</PageTitle>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useEffect } from 'react';
import { useParams } from 'react-router-dom';

import { useGetStudyReviews } from '@api/reviews';
@@ -16,15 +15,11 @@ const ReviewTabPanel: React.FC = () => {
const { studyId: _studyId } = useParams<{ studyId: string }>();
const studyId = Number(_studyId);

const { userInfo, fetchUserInfo } = useUserInfo();
const { userInfo } = useUserInfo();
const { isOwnerOrMember } = useUserRole({ studyId });

const { data, isFetching, refetch, isError, isSuccess } = useGetStudyReviews({ studyId });

useEffect(() => {
fetchUserInfo();
}, []);

const handlePostSuccess = () => {
alert('댓글을 추가했습니다');
refetch();