Skip to content

Commit ee1287d

Browse files
committed
refactor : Sidebar(main) 페이지 코드 리팩토링
- 각 요소들을 부분별로 분리 1. MainPage에서 Sidebar를 컴포넌트로 분리 2. Sidebar에서 아이콘을 생성하는 PageIcon 컴포넌트를 분리하여 재사용 3. ProjectPage를 이동하는 아이콘을 모은 PageLinkIcons 컴포넌트를 ProjectSidebar로부터 분리 4. 알람, 멤버확인 등 util 기능을 담당하는 아이콘을 모은 UtilIcons 컴포넌트를 ProjectSidebar로부터 분리
1 parent adf7b8f commit ee1287d

File tree

9 files changed

+150
-87
lines changed

9 files changed

+150
-87
lines changed

frontend/src/assets/icons/member.svg

+2-2
Loading

frontend/src/assets/icons/notifications.svg

+2-2
Loading

frontend/src/assets/icons/pageout.svg

+2-2
Loading
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { SVGReactElement } from "../../types/common";
2+
import { Link } from "react-router-dom";
3+
import ChevronRightIcon from "../../assets/icons/chevron-right.svg?react";
4+
5+
interface PageIconProps {
6+
Icon: SVGReactElement;
7+
activated: boolean;
8+
to: string;
9+
pageName: string;
10+
}
11+
12+
const PageIcon = ({ Icon, activated, to, pageName }: PageIconProps): JSX.Element => {
13+
if (activated) {
14+
return (
15+
<div className="flex justify-between items-center pl-2 pr-[0.3125rem] py-[0.3125rem] rounded-full cursor-pointer bg-white text-middle-green transition-all w-fit hover:min-w-40 hover:shadow-box hover:gap-2 group">
16+
<Icon width={24} height={24} fill="#3A5624" className="shrink-0" />
17+
<p className="text-base font-bold shrink-0 select-none hidden group-hover:inline-flex">
18+
{pageName}
19+
</p>
20+
<ChevronRightIcon width={18} height={18} stroke="#3A5624" className="shrink-0" />
21+
</div>
22+
);
23+
}
24+
25+
return (
26+
<Link
27+
to={to}
28+
className="group flex justify-center items-center w-[3.4375rem] text-white py-[0.3125rem] transition-all rounded-full cursor-pointer hover:min-w-40 hover:shadow-box hover:gap-2 hover:bg-white hover:text-middle-green hover:pl-2 hover:pr-[0.3125rem] hover:justify-between"
29+
>
30+
<Icon
31+
width={24}
32+
height={24}
33+
fill="#FFFFFF"
34+
className="shrink-0 group-hover:fill-middle-green"
35+
/>
36+
<p className="text-base font-bold shrink-0 select-none hidden group-hover:inline-flex">
37+
{pageName}
38+
</p>
39+
<ChevronRightIcon
40+
width={18}
41+
height={18}
42+
stroke="#3A5624"
43+
className="shrink-0 hidden group-hover:inline-flex"
44+
/>
45+
</Link>
46+
);
47+
};
48+
49+
export default PageIcon;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import PageIcon from "./PageIcon";
2+
import LandingIcon from "../../assets/icons/landing.svg?react";
3+
import BacklogIcon from "../../assets/icons/backlog.svg?react";
4+
import SprintIcon from "../../assets/icons/sprint.svg?react";
5+
import SettingIcon from "../../assets/icons/settings.svg?react";
6+
import { LINK_URL } from "../../constants/path";
7+
import { ProjectSidebarProps } from "../../types/main";
8+
9+
const PageLinkIcons = ({ pathname, projectId }: ProjectSidebarProps) => {
10+
return (
11+
<div className="flex flex-col pl-[0.9375rem] pt-[1.5625rem] w-[5.3125rem] gap-5">
12+
<PageIcon
13+
Icon={LandingIcon}
14+
activated={pathname === LINK_URL.MAIN(projectId)}
15+
to={LINK_URL.MAIN(projectId)}
16+
pageName="메인페이지"
17+
/>
18+
<PageIcon
19+
Icon={BacklogIcon}
20+
activated={pathname === LINK_URL.BACKLOG(projectId)}
21+
to={LINK_URL.BACKLOG(projectId)}
22+
pageName="백로그"
23+
/>
24+
<PageIcon
25+
Icon={SprintIcon}
26+
activated={pathname === LINK_URL.SPRINT(projectId)}
27+
to={LINK_URL.SPRINT(projectId)}
28+
pageName="스프린트"
29+
/>
30+
<PageIcon
31+
Icon={SettingIcon}
32+
activated={pathname === LINK_URL.SETTINGS(projectId)}
33+
to={LINK_URL.SETTINGS(projectId)}
34+
pageName="프로젝트 설정"
35+
/>
36+
</div>
37+
);
38+
};
39+
40+
export default PageLinkIcons;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ProjectSidebarProps } from "../../types/main";
2+
import PageLinkIcons from "./PageLinkIcons";
3+
import UtilIcons from "./UtilIcons";
4+
5+
const ProjectSidebar = ({ pathname, projectId }: ProjectSidebarProps) => {
6+
return (
7+
<div className="flex flex-col justify-between h-[40.5rem] bg-gradient-to-t from-sidebar-linear-from to-sidebar-linear-to rounded-lg shadow-box z-10">
8+
<PageLinkIcons {...{ pathname, projectId }} />
9+
<UtilIcons {...{ pathname, projectId }} />
10+
</div>
11+
);
12+
};
13+
14+
export default ProjectSidebar;
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { LINK_URL, ROUTER_URL } from "../../constants/path";
2+
import { DEFAULT_MEMBER } from "../../constants/projects";
3+
import { ProjectSidebarProps } from "../../types/main";
4+
import PageIcon from "./PageIcon";
5+
import PageOutIcon from "../../assets/icons/pageout.svg?react";
6+
import NotificationIcon from "../../assets/icons/notifications.svg?react";
7+
import MemberIcon from "../../assets/icons/member.svg?react";
8+
9+
const UtilIcons = ({ pathname, projectId }: ProjectSidebarProps) => {
10+
const { imageUrl } = JSON.parse(window.localStorage.getItem("member") ?? DEFAULT_MEMBER);
11+
return (
12+
<div className="flex flex-col pl-[0.9375rem] pb-[1.875rem] w-[5.3125rem] gap-5">
13+
{pathname !== LINK_URL.MAIN(projectId) && (
14+
<button>
15+
<MemberIcon width={24} height={24} fill="#FFFFFF" className="ml-[0.96875rem]" />
16+
</button>
17+
)}
18+
<button>
19+
<NotificationIcon width={24} height={24} fill={"#FFFFFF"} className="ml-[0.96875rem]" />
20+
</button>
21+
<PageIcon
22+
Icon={PageOutIcon}
23+
activated={false}
24+
to={ROUTER_URL.PROJECTS}
25+
pageName="내 프로젝트"
26+
/>
27+
<div className="w-10 h-10 ml-[0.46875rem] rounded-full overflow-hidden">
28+
<img src={imageUrl} alt="프로필 이미지 사진" />
29+
</div>
30+
</div>
31+
);
32+
};
33+
34+
export default UtilIcons;

frontend/src/pages/main/MainPage.tsx

+3-81
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,13 @@
1-
import { Outlet, Link, useLocation, useParams } from "react-router-dom";
2-
import { SVGReactElement } from "../../types/common";
3-
import { LINK_URL } from "../../constants/path";
4-
import Landing from "../../assets/icons/landing.svg?react";
5-
import ChevronRight from "../../assets/icons/chevron-right.svg?react";
6-
import Backlog from "../../assets/icons/backlog.svg?react";
7-
import Sprint from "../../assets/icons/sprint.svg?react";
8-
import Setting from "../../assets/icons/settings.svg?react";
9-
10-
interface PageIconProps {
11-
Icon: SVGReactElement;
12-
activated: boolean;
13-
to: string;
14-
pageName: string;
15-
}
16-
17-
const PageIcon = ({ Icon, activated, to, pageName }: PageIconProps): JSX.Element => {
18-
if (activated) {
19-
return (
20-
<div className="flex justify-between items-center pl-2 pr-[0.3125rem] py-[0.3125rem] rounded-full cursor-pointer bg-white text-middle-green transition-all w-fit hover:min-w-40 hover:shadow-box hover:gap-2 group">
21-
<Icon width={24} height={24} fill="#3A5624" className="shrink-0" />
22-
<p className="text-base font-bold shrink-0 select-none hidden group-hover:inline-flex">
23-
{pageName}
24-
</p>
25-
<ChevronRight width={18} height={18} stroke="#3A5624" className="shrink-0" />
26-
</div>
27-
);
28-
}
29-
30-
return (
31-
<Link
32-
to={to}
33-
className="group flex justify-center items-center w-[3.4375rem] text-white py-[0.3125rem] transition-all rounded-full cursor-pointer hover:min-w-40 hover:shadow-box hover:gap-2 hover:bg-white hover:text-middle-green hover:pl-2 hover:pr-[0.3125rem] hover:justify-between"
34-
>
35-
<Icon
36-
width={24}
37-
height={24}
38-
fill="#FFFFFF"
39-
className="shrink-0 group-hover:fill-middle-green"
40-
/>
41-
<p className="text-base font-bold shrink-0 select-none hidden group-hover:inline-flex">
42-
{pageName}
43-
</p>
44-
<ChevronRight
45-
width={18}
46-
height={18}
47-
stroke="#3A5624"
48-
className="shrink-0 hidden group-hover:inline-flex"
49-
/>
50-
</Link>
51-
);
52-
};
1+
import { Outlet, useLocation, useParams } from "react-router-dom";
2+
import ProjectSidebar from "../../components/main/ProjectSidebar";
533

544
const MainPage = () => {
555
const { pathname } = useLocation();
566
const { projectId } = useParams();
577
if (!projectId) throw Error("잘못된 ProjectID 입니다.");
588
return (
599
<div className="flex justify-center items-center h-screen min-w-[76rem] gap-9">
60-
<div className="flex flex-col justify-between h-[40.5rem] bg-gradient-to-t from-sidebar-linear-from to-sidebar-linear-to rounded-lg shadow-box z-10">
61-
<div className="flex flex-col pl-[0.9375rem] pt-[1.5625rem] w-[5.3125rem] gap-5 text-white">
62-
<PageIcon
63-
Icon={Landing}
64-
activated={pathname === LINK_URL.MAIN(projectId)}
65-
to={LINK_URL.MAIN(projectId)}
66-
pageName="메인페이지"
67-
/>
68-
<PageIcon
69-
Icon={Backlog}
70-
activated={pathname === LINK_URL.BACKLOG(projectId)}
71-
to={LINK_URL.BACKLOG(projectId)}
72-
pageName="백로그"
73-
/>
74-
<PageIcon
75-
Icon={Sprint}
76-
activated={pathname === LINK_URL.SPRINT(projectId)}
77-
to={LINK_URL.SPRINT(projectId)}
78-
pageName="스프린트"
79-
/>
80-
<PageIcon
81-
Icon={Setting}
82-
activated={pathname === LINK_URL.SETTINGS(projectId)}
83-
to={LINK_URL.SETTINGS(projectId)}
84-
pageName="프로젝트 설정"
85-
/>
86-
</div>
87-
<div className="w-[5.3125rem]"></div>
88-
</div>
10+
<ProjectSidebar {...{ pathname, projectId }} />
8911
<div className="h-[40.5rem] min-w-[67.9375rem] border-2">
9012
<Outlet />
9113
</div>

frontend/src/types/main.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface ProjectSidebarProps {
2+
pathname: string;
3+
projectId: string;
4+
}

0 commit comments

Comments
 (0)