Skip to content

Commit

Permalink
Merge pull request #220 from BCSDLab/feature/#199
Browse files Browse the repository at this point in the history
�[영양사]사장님, 영양사 url 분기 생성
  • Loading branch information
junghaesung79 authored Apr 9, 2024
2 parents b41260e + dac525a commit a497bc9
Show file tree
Hide file tree
Showing 24 changed files with 224 additions and 100 deletions.
78 changes: 59 additions & 19 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Routes, Route } from 'react-router-dom';
import DefaultLayout from 'layout/DefaultLayout';
import {
Routes, Route, Navigate, Outlet,
} from 'react-router-dom';
import OwnerLayout from 'layout/OwnerLayout';
import CoopLayout from 'layout/CoopLayout';
import Login from 'page/Auth/Login';
import Signup from 'page/Auth/Signup';
import FindPassword from 'page/Auth/FindPassword/SendAuthNumber';
Expand All @@ -13,31 +16,68 @@ import PageNotFound from 'page/Error/PageNotFound';
import ModifyMenu from 'page/ModifyMenu';
import { Suspense } from 'react';
import Toast from 'component/common/Toast';
import { UserType } from 'model/auth';
import Coop from 'page/Coop';
import useUserTypeStore from 'store/userType';

interface ProtectedRouteProps {
userTypeRequired: UserType;
}

function ProtectedRoute({ userTypeRequired }: ProtectedRouteProps) {
const { userType, setUserType } = useUserTypeStore();
setUserType();

if (userType !== userTypeRequired) {
if (userType === 'OWNER') {
return <Navigate to="/owner" replace />;
}
if (userType === 'COOP') {
return <Navigate to="/coop" replace />;
}
if (userType === null) {
return <Navigate to="/login" replace />;
}
}

return <Outlet />;
}

function App() {
return (
<Suspense fallback={<div />}>
<Routes>
<Route path="/" element={<DefaultLayout />}>
<Route path="/" element={<MyStorePage />} />
<Route path="/store-registration" element={<ShopRegistration />} />
<Route path="/add-menu" element={<AddMenu />} />
<Route path="/modify-menu/:menuId" element={<ModifyMenu />} />
<Route path="/modify-info" element={<PageNotFound />} />
<Route path="/menu-management" element={<PageNotFound />} />
<Route path="/order-management" element={<PageNotFound />} />
<Route path="/sales-management" element={<PageNotFound />} />
<Route path="/shop-add" element={<PageNotFound />} />
<Route path="/coop" element={<Coop />} />
<Route path="/" element={<Navigate to="/owner" />} />
<Route element={<ProtectedRoute userTypeRequired="OWNER" />}>
<Route path="/owner" element={<OwnerLayout />}>
<Route path="/owner" element={<MyStorePage />} />
<Route path="/owner/shop-registration" element={<ShopRegistration />} />
<Route path="/owner/add-menu" element={<AddMenu />} />
<Route path="/owner/modify-menu/:menuId" element={<ModifyMenu />} />
<Route path="/owner/modify-info" element={<PageNotFound />} />
<Route path="/owner/menu-management" element={<PageNotFound />} />
<Route path="/owner/order-management" element={<PageNotFound />} />
<Route path="/owner/sales-management" element={<PageNotFound />} />
<Route path="/owner/shop-add" element={<PageNotFound />} />
</Route>
</Route>
<Route element={<ProtectedRoute userTypeRequired="COOP" />}>
<Route path="/coop" element={<CoopLayout />}>
<Route path="/coop" element={<Coop />} />
</Route>
</Route>

<Route element={<AuthLayout />}>
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
<Route path="/find-id" element={<PageNotFound />} />
<Route path="/find-password" element={<FindPassword />} />
<Route path="/new-password" element={<NewPassword />} />
<Route path="/complete-change-password" element={<CompleteChangePassword />} />
<Route element={<ProtectedRoute userTypeRequired={null} />}>
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
<Route path="/find-id" element={<PageNotFound />} />
<Route path="/find-password" element={<FindPassword />} />
</Route>
<Route element={<ProtectedRoute userTypeRequired="OWNER" />}>
<Route path="/new-password" element={<NewPassword />} />
<Route path="/complete-change-password" element={<CompleteChangePassword />} />
</Route>
</Route>
</Routes>
<Toast />
Expand Down
14 changes: 9 additions & 5 deletions src/api/auth/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { accessClient, client } from 'api';
import { LoginParams, LoginResponse, UserResponse } from 'model/auth';
// import {
// LoginParams, LoginResponse, UserResponse,
// } from 'api/auth/model';
import {
LoginParams, LoginResponse, UserResponse, UserTypeResponse,
} from 'model/auth';

export const postLogin = async (param: LoginParams) => {
const { data } = await client.post<LoginResponse>('/user/login', param);
Expand All @@ -11,7 +10,12 @@ export const postLogin = async (param: LoginParams) => {

export const postLogout = () => accessClient.post('/user/logout');

export const getMe = async () => {
export const getUserType = async () => {
const { data } = await accessClient.get<UserTypeResponse>('/user/auth');
return UserTypeResponse.parse(data);
};

export const getOwnerInfo = async () => {
const { data } = await accessClient.get<UserResponse>('/owner');
return UserResponse.parse(data);
};
Expand Down
File renamed without changes.
38 changes: 21 additions & 17 deletions src/component/common/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { ReactComponent as LogoIcon } from 'assets/svg/common/koin-logo.svg';
import { ReactComponent as MobileLogoIcon } from 'assets/svg/common/mobile-koin-logo.svg';
import { ReactComponent as MenuIcon } from 'assets/svg/common/hamburger-menu.svg';
import { ReactComponent as BackArrowIcon } from 'assets/svg/common/back-arrow.svg';
import { Link, useLocation } from 'react-router-dom';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import CATEGORY from 'utils/constant/category';
import cn from 'utils/ts/className';
import useMediaQuery from 'utils/hooks/useMediaQuery';
import { createPortal } from 'react-dom';
import { postLogout } from 'api/auth';
import useUserStore from 'store/user';
import { useLogout } from 'query/auth';
import usePrevPathStore from 'store/path';
import styles from './Header.module.scss';
import useMobileSidebar from './hooks/useMobileSidebar';
import useMegaMenu from './hooks/useMegaMenu';
Expand All @@ -35,18 +36,21 @@ function Header() {
hideSidebar,
} = useMobileSidebar(pathname, isMobile);
const isMain = true;
const { user, removeUser } = useUserStore();
const { user } = useUserStore();
const { logout } = useLogout();
const navigate = useNavigate();
const { setPrevPath } = usePrevPathStore((state) => state);

const logout = () => {
postLogout()
.then(() => {
sessionStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
removeUser();
});
const handleLogout = () => {
logout(undefined, {
onSettled: () => {
setPrevPath('/login');
navigate('/login');
},
});
};

if ((pathname === '/add-menu' || pathname.startsWith('/modify-menu/')) && isMobile) {
if ((pathname === '/owner/add-menu' || pathname.startsWith('/owner/modify-menu/')) && isMobile) {
return (
<header className={styles['add-menu-header']}>
<button
Expand All @@ -56,7 +60,7 @@ function Header() {
>
<BackArrowIcon title="뒤로 가기 버튼" />
</button>
<div className={styles['add-menu-header__caption']}>{pathname === '/add-menu' ? '메뉴추가' : '메뉴수정'}</div>
<div className={styles['add-menu-header__caption']}>{pathname === '/owner/add-menu' ? '메뉴추가' : '메뉴수정'}</div>
</header>
);
}
Expand Down Expand Up @@ -86,7 +90,7 @@ function Header() {
</button>
)}
<span className={styles.mobileheader__title}>
{pathname === '/' || pathname === '/coop' ? (
{pathname === '/owner' || pathname === '/coop' ? (
<MobileLogoIcon title="코인 로고" />
) : (CATEGORY
.flatMap((categoryValue) => categoryValue.submenu)
Expand Down Expand Up @@ -128,12 +132,12 @@ function Header() {
</div>
<ul className={styles['mobileheader__auth-menu']}>
<li className={styles['mobileheader__my-info']}>
<Link to="/modify-info">
<Link to="/owner/modify-info">
내 정보
</Link>
</li>
<li className={styles.mobileheader__link}>
<button type="button" onClick={logout}>
<button type="button" onClick={handleLogout}>
로그아웃
</button>
</li>
Expand Down Expand Up @@ -245,12 +249,12 @@ function Header() {
<ul className={styles['header__auth-menu']}>
{/* Auth 완료시 수정 필요 */}
<li className={styles['header__auth-link']}>
<Link to="/modify-info">
<Link to="/owner/modify-info">
정보수정
</Link>
</li>
<li className={styles['header__auth-link']}>
<button type="button" onClick={logout}>
<button type="button" onClick={handleLogout}>
로그아웃
</button>
</li>
Expand Down
20 changes: 2 additions & 18 deletions src/layout/AuthLayout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,11 @@
import { Outlet, useNavigate } from 'react-router-dom';
import ErrorBoundary from 'component/common/ErrorBoundary';
import { Outlet } from 'react-router-dom';
import Copyright from 'component/common/Copyright';
import useUserStore from 'store/user';
import { useEffect } from 'react';
import styles from './AuthLayout.module.scss';

export default function AuthLayout() {
const navigate = useNavigate();
const { user, setUser } = useUserStore();

useEffect(() => {
// @ChoiWonBeen 토큰없음 에러제거. TODO: setUser가 에러를 다루는 문제 제거
setUser().catch(() => {});
if (user) {
navigate('/', { replace: true });
}
}, [setUser, user, navigate]);

return (
<div className={styles.template}>
<ErrorBoundary message="사용자를 로드하는데 실패했습니다.">
<Outlet />
</ErrorBoundary>
<Outlet />
<Copyright />
</div>
);
Expand Down
11 changes: 11 additions & 0 deletions src/layout/CoopLayout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Outlet } from 'react-router-dom';
import Header from 'component/common/Header';

export default function CoopLayout() {
return (
<div>
<Header />
<Outlet />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import usePrevPathStore from 'store/path';
import useUserStore from 'store/user';
import useErrorBoundary from 'utils/hooks/useErrorBoundary';

export default function DefaultLayout() {
export default function OwnerLayout() {
const navigate = useNavigate();
const { user, setUser } = useUserStore((state) => state);
const setPrevPath = usePrevPathStore((state) => state.setPrevPath);
Expand All @@ -18,8 +18,8 @@ export default function DefaultLayout() {
setUser()
.catch(handleErrorBoundary)
.catch(() => {
setPrevPath('/store-registration');
navigate('/login', { replace: true });
setPrevPath('/owner/shop-registration');
navigate('/owner/shop-registration');
});
}
}, [handleErrorBoundary, setUser, setPrevPath, navigate, user]);
Expand All @@ -28,7 +28,7 @@ export default function DefaultLayout() {
<div>
{user && (
<>
{location.pathname !== '/store-registration' && <Header />}
{location.pathname !== '/owner/shop-registration' && <Header />}
<ErrorBoundary message="에러가 발생했습니다.">
<Outlet />
</ErrorBoundary>
Expand Down
17 changes: 16 additions & 1 deletion src/model/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ export type LoginParams = z.infer<typeof LoginParams>;
export const LoginResponse = z.object({
refresh_token: z.string(),
token: z.string(),
user_type: z.string(),
user_type: z.union([
z.literal('OWNER'),
z.literal('COOP'),
z.null(),
]),
});

export type LoginResponse = z.infer<typeof LoginResponse>;
Expand Down Expand Up @@ -57,6 +61,17 @@ export type UserResponse = z.infer<typeof UserResponse>;

export const User = z.nullable(UserResponse);

export const UserTypeResponse = z.object({
user_type: z.union([
z.literal('OWNER'),
z.literal('COOP'),
]),
});

export type UserTypeResponse = z.infer<typeof UserTypeResponse>;

export type UserType = 'OWNER' | 'COOP' | null;

export type User = z.infer<typeof User>;

export interface LoginForm extends LoginParams {
Expand Down
2 changes: 1 addition & 1 deletion src/page/AddMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function AddMenu() {
const { resetMenuName, resetCategoryIds } = useAddMenuStore();
const { setMenuError, setCategoryError } = useErrorMessageStore();
const goMyShop = () => {
navigate('/');
navigate('/owner');
};
const {
value: isGoMyShopModal,
Expand Down
1 change: 0 additions & 1 deletion src/page/Auth/Login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export default function Login() {
const { loginError, loginErrorCode } = useErrorMessageStore();
const [emailError, setEmailError] = useState('');
const { value: isModalOpen, changeValue: toggle } = useBooleanState(false);

const isError = isServerError || isFormError;

const {
Expand Down
7 changes: 7 additions & 0 deletions src/page/CoopPage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function CoopPage() {
return (
<>
coop page
</>
);
}
2 changes: 1 addition & 1 deletion src/page/Error/PageNotFound/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function PageNotFound() {
<button
type="button"
className={styles.content__button}
onClick={() => navigate('/')}
onClick={() => navigate('/owner')}
>
메인 화면 바로가기
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/page/ModifyMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function ModifyMenu() {
const { menuData, modifyMenuMutation } = useMenuInfo(Number(menuId));

const goMyShop = () => {
navigate('/');
navigate('/owner');
};

const toggleConfirmClick = () => {
Expand Down
2 changes: 1 addition & 1 deletion src/page/MyShopPage/components/CatagoryMenuList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import styles from './CatagoryMenuList.module.scss';
export default function CatagoryMenuList({ menuCategory }: { menuCategory: MenuCategory }) {
const navigate = useNavigate();
const handleMenuClick = (menuId: number) => {
navigate(`/modify-menu/${menuId}`);
navigate(`/owner/modify-menu/${menuId}`);
};
return (
<div>
Expand Down
6 changes: 3 additions & 3 deletions src/page/MyShopPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default function MyShopPage() {

useEffect(() => {
if (!shopData && !isLoading) {
navigate('/store-registration');
navigate('/owner/shop-registration');
}
}, [shopData, navigate, isLoading]);

Expand All @@ -63,7 +63,7 @@ export default function MyShopPage() {
<>
<div className={styles.mobileheader}>
<h1 className={styles.mobileheader__title}>가게정보</h1>
<Link to="/add-menu">
<Link to="/owner/add-menu">
<button
type="button"
className={styles['mobileheader__btn-add']}
Expand Down Expand Up @@ -92,7 +92,7 @@ export default function MyShopPage() {
<div className={styles.container}>
<div className={styles.header}>
<h1 className={styles.header__title}>가게정보</h1>
<Link to="/add-menu">
<Link to="/owner/add-menu">
<button
type="button"
className={styles['header__btn-add']}
Expand Down
Loading

0 comments on commit a497bc9

Please sign in to comment.