Skip to content

Commit

Permalink
Merge pull request #82 from YAPP-Github/feature/FE-059
Browse files Browse the repository at this point in the history
  • Loading branch information
sxungchxn authored Jul 7, 2023
2 parents 70ee517 + 922c652 commit 29c3314
Show file tree
Hide file tree
Showing 16 changed files with 90 additions and 30 deletions.
8 changes: 1 addition & 7 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,8 @@ const nextConfig = {
},
// 프록시 설정
async rewrites(){
const rewriteTargets = [];
const API_ENDPOINT = process.env.API_URL ?? process.env.NEXT_PUBLIC_API_URL;

const rewriteTargets = [
{
source: '/api/login',
destination: `${API_ENDPOINT}/v1/users/login`
},
]

if(process.env.NODE_ENV === 'development') {
rewriteTargets.push({
Expand Down
4 changes: 4 additions & 0 deletions src/api/user/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class UserAPI {
})
.json<Profile | undefined>();
}

async postLogout() {
return request.post('v1/users/logout').json();
}
}

export const userAPI = new UserAPI();
2 changes: 2 additions & 0 deletions src/api/user/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export { default as useProfile } from './useProfile';

export { default as useLogin } from './useLogin';

export { default as useLogout } from './useLogout';
16 changes: 16 additions & 0 deletions src/api/user/hooks/useLogout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useQueryClient } from '@tanstack/react-query';
import { useMutation } from '@/hooks';
import { userKeys } from '@/api/user/queryKeys';
import { userAPI } from '@/api/user/api';

const useLogout = () => {
const queryClient = useQueryClient();

return useMutation(userAPI.postLogout, {
onSuccess: () => {
void queryClient.invalidateQueries(userKeys.profile());
},
});
};

export default useLogout;
4 changes: 3 additions & 1 deletion src/app/board/components/AsideSection/AsideSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useRouter } from 'next/navigation';
import { Button, Typography, Dropdown, SvgIcon, Toast } from '@/components';
import { JoinModal, DeleteModal, CancelJoinModal, ParticipantsList } from '@/app/board/components';
import { useProfile } from '@/api/hooks';
import { useOverlay, useClipBoard } from '@/hooks';
import { useOverlay, useClipBoard, useLoginRedirect } from '@/hooks';
import { BOARD_STATUS, TOAST_TEXT } from '@/app/board/constants';
import { BoardDetail } from '@/api/types';
import { wrapper, counterText, listBottomSpace, dropdown, dropdownMenu, buttonGroup } from './AsideSection.css';
Expand All @@ -16,6 +16,7 @@ interface Props {
const AsideSection = ({ board }: Props) => {
const router = useRouter();
const { data: profile } = useProfile();
const { redirectToLogin } = useLoginRedirect();
const [openModal, closeModal] = useOverlay();
const [openToast, closeToast] = useOverlay();
const [, copyToClipBoard] = useClipBoard();
Expand All @@ -32,6 +33,7 @@ const AsideSection = ({ board }: Props) => {
};

const handleClickJoinButton = () => {
if (!profile) return redirectToLogin();
openModal(
<JoinModal
boardId={boardId}
Expand Down
9 changes: 8 additions & 1 deletion src/app/home/components/HeroSection/HeroSection.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
'use client';

import Link from 'next/link';
import { useProfile } from '@/api/user';
import { Button, Typography } from '@/components';
import { GradientText } from '@/app/home/components';
import { section, title, subTitle, button } from './HeroSection.css';
import { useLoginRedirect } from '@/hooks';

const HeroSection = () => {
const { data: profile } = useProfile();
const { loginPath } = useLoginRedirect();

return (
<section className={section}>
<Typography variant="display2" as="h1" className={title}>
Expand All @@ -20,7 +27,7 @@ const HeroSection = () => {
가볍게 대화해보세요!
</Typography>

<Link href={'/write'}>
<Link href={profile ? '/write' : loginPath}>
<Button color="primary" className={button}>
<Typography color="white" variant="title2">
우리 회사 먹팟 만들기
Expand Down
5 changes: 4 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import '@/styles/globals.css';
import localFont from 'next/font/local';
import Script from 'next/script';
import { OverlayProvider, QueryProvider } from '@/providers';
import { ProfileProvider } from '@/providers/server';

const pretendardFont = localFont({
src: '../../public/PretendardVariable.woff2',
Expand Down Expand Up @@ -42,7 +43,9 @@ export default function RootLayout({ children }: { children: React.ReactNode })
/>
</noscript>
<QueryProvider>
<OverlayProvider>{children}</OverlayProvider>
<ProfileProvider>
<OverlayProvider>{children}</OverlayProvider>
</ProfileProvider>
</QueryProvider>
</body>
</html>
Expand Down
6 changes: 3 additions & 3 deletions src/app/login/components/LoginForm/LoginForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import { useRouter } from 'next/navigation';
import { useLogin } from '@/api/hooks';
import { useLoginRedirect } from '@/hooks';
import { Input, InputSection } from '@/components';
import { wrapper, form } from './LoginForm.css';
import { FormProvider, FieldValues, SubmitHandler } from 'react-hook-form';
Expand All @@ -10,8 +10,8 @@ import { useLoginContext } from '../../contexts/LoginContext';
import { LoginButton } from '../../components';

const LoginForm = () => {
const router = useRouter();
const { mutate: login } = useLogin();
const { redirectBack } = useLoginRedirect();
const { keep } = useLoginContext();
const { method, errors, setSubmitError, resetSubmitError } = useLoginForm();

Expand All @@ -22,7 +22,7 @@ const LoginForm = () => {
{ email, password, keep },
{
onSuccess: () => {
router.replace('/');
redirectBack();
},
onError: (error) => {
setSubmitError(error.message);
Expand Down
9 changes: 2 additions & 7 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Logo } from '@/components';
import { Suspense } from '@suspensive/react';
import HeaderWrapper from './HeaderWrapper';
import HydratedHeaderActions from './HydratedHeaderActions';
import HeaderActions from './HeaderActions';

interface Props {
/** 헤더의 action buttons가 필요한지의 여부 */
Expand All @@ -12,11 +11,7 @@ const Header = async ({ actionRequired = true }: Props) => {
return (
<HeaderWrapper>
<Logo />
{actionRequired && (
<Suspense>
<HydratedHeaderActions />
</Suspense>
)}
{actionRequired && <HeaderActions />}
</HeaderWrapper>
);
};
Expand Down
7 changes: 6 additions & 1 deletion src/components/Header/LoginActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
SvgIcon,
Typography,
} from '@/components';
import { useLogout } from '@/api/user';
import { type Profile as ProfileData } from '@/types/data';
import { dropdownToggle } from './Header.css';
import Link from 'next/link';
Expand All @@ -17,6 +18,8 @@ interface Props {
}

const LoginActions = ({ profile }: Props) => {
const { mutate: logout } = useLogout();

return (
<>
<Link href={'/write'}>
Expand All @@ -32,7 +35,9 @@ const LoginActions = ({ profile }: Props) => {
<SvgIcon id="chevrondown" width={24} height={24} />
</DropdownToggle>
<DropdownMenu placement="bottomRight" style={{ width: '236px' }}>
<DropdownItem itemKey="logout">로그아웃</DropdownItem>
<DropdownItem itemKey="logout" onClick={logout}>
로그아웃
</DropdownItem>
</DropdownMenu>
</Dropdown>
</>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Header/UnloginActions.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Button } from '@/components';
import { useLoginRedirect } from '@/hooks';
import Link from 'next/link';

const UnloginActions = () => {
const { loginPath } = useLoginRedirect();
return (
<Link href="/login">
<Link href={`${loginPath}`}>
<Button color="explain" size="paddingSmall">
로그인
</Button>
Expand Down
2 changes: 2 additions & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export { default as useIntersectObserver } from './useIntersectObserver/useInter
export { default as useOverlay } from './useOverlay/useOverlay';

export { default as useClipBoard } from './useClipBoard/useClipBoard';

export { default as useLoginRedirect } from './useLoginRedirect/useLoginRedirect';
30 changes: 30 additions & 0 deletions src/hooks/useLoginRedirect/useLoginRedirect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useCallback } from 'react';
import { useRouter, usePathname, useSearchParams } from 'next/navigation';

const HOME_PATH = '/';
const LOGIN_PATH = '/login';
const REDIRECT_QUERY = 'redirectPath';

const useLoginRedirect = () => {
const router = useRouter();
const searchParams = useSearchParams();
const currentPathname = usePathname();

const loginPath = `${LOGIN_PATH}?${REDIRECT_QUERY}=${currentPathname}`;

const redirectToLogin = useCallback(() => {
router.push(`${LOGIN_PATH}?${REDIRECT_QUERY}=${currentPathname}`);
}, [router, currentPathname]);

const redirectBack = useCallback(() => {
if (searchParams.has(REDIRECT_QUERY)) {
router.replace(searchParams.get(REDIRECT_QUERY) as string);
} else {
router.replace(HOME_PATH);
}
}, [router, searchParams]);

return { loginPath, redirectToLogin, redirectBack };
};

export default useLoginRedirect;
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { ReactNode } from 'react';
import { dehydrate, Hydrate } from '@tanstack/react-query';
import getQueryClient from '@/utils/getQueryClients';
import { api, queryKeys } from '@/api';
import HeaderActions from './HeaderActions';

const HydratedHeaderActions = async () => {
const ProfileProvider = async ({ children }: { children: ReactNode }) => {
const queryClient = getQueryClient();
await queryClient.prefetchQuery(queryKeys.user.profile(), () => api.user.getProfile());
const dehydratedState = dehydrate(queryClient);

return (
<Hydrate state={dehydratedState}>
<HeaderActions />
</Hydrate>
);
return <Hydrate state={dehydratedState}>{children}</Hydrate>;
};

export default HydratedHeaderActions;
export default ProfileProvider;
1 change: 1 addition & 0 deletions src/providers/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as QueryProvider } from './QueryProvider';

export { OverlayProvider } from './OverlayProvider';
1 change: 1 addition & 0 deletions src/providers/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as ProfileProvider } from './ProfileProvider';

0 comments on commit 29c3314

Please sign in to comment.