diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f62ac1da7..740f2a360 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -7,8 +7,10 @@ import LoginPage from "@/pages/LoginPage"; import MainPage from "@/pages/MainPage"; import AdminMainPage from "@/pages/admin/AdminMainPage"; import LoadingAnimation from "@/components/Common/LoadingAnimation"; +import ProfilePage from "./pages/ProfilePage"; import "./firebase-messaging-sw" + const NotFoundPage = lazy(() => import("@/pages/NotFoundPage")); const LoginFailurePage = lazy(() => import("@/pages/LoginFailurePage")); const AdminLayout = lazy(() => import("@/pages/admin/AdminLayout")); @@ -29,7 +31,8 @@ function App(): React.ReactElement { } /> } /> } /> - } /> + } /> + } /> {/* admin용 라우터 */} }> diff --git a/frontend/src/assets/images/link.svg b/frontend/src/assets/images/link.svg new file mode 100644 index 000000000..bd9167557 --- /dev/null +++ b/frontend/src/assets/images/link.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/src/assets/images/profile-circle.svg b/frontend/src/assets/images/profile-circle.svg new file mode 100644 index 000000000..79107f64f --- /dev/null +++ b/frontend/src/assets/images/profile-circle.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/src/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx b/frontend/src/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx index 859a9b3fd..ca4c2486f 100644 --- a/frontend/src/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx +++ b/frontend/src/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx @@ -109,6 +109,11 @@ const LeftMainNavContainer = ({ isAdmin }: { isAdmin?: boolean }) => { closeAll(); }; + const onClickProfileButton = () => { + navigator("profile"); + closeAll(); + }; + const onClickLogoutButton = (): void => { const adminToken = isAdmin ? "admin_" : ""; if (import.meta.env.VITE_IS_LOCAL === "true") { @@ -138,6 +143,7 @@ const LeftMainNavContainer = ({ isAdmin }: { isAdmin?: boolean }) => { onClickSearchButton={onClickSearchButton} onClickLogoutButton={onClickLogoutButton} onClickClubButton={onClickClubButton} + onClickProfileButton={onClickProfileButton} isAdmin={isAdmin} /> ); diff --git a/frontend/src/components/LeftNav/LeftMainNav/LeftMainNav.tsx b/frontend/src/components/LeftNav/LeftMainNav/LeftMainNav.tsx index 5a1edc256..0b0211a6a 100644 --- a/frontend/src/components/LeftNav/LeftMainNav/LeftMainNav.tsx +++ b/frontend/src/components/LeftNav/LeftMainNav/LeftMainNav.tsx @@ -10,6 +10,7 @@ interface ILeftMainNav { onClickLentLogButton: React.MouseEventHandler; onClickSearchButton: React.MouseEventHandler; onClickClubButton: React.MouseEventHandler; + onClickProfileButton: React.MouseEventHandler; isAdmin?: boolean; } @@ -23,6 +24,7 @@ const LeftMainNav = ({ onClickLentLogButton, onClickSearchButton, onClickClubButton, + onClickProfileButton, isAdmin, }: ILeftMainNav) => { return ( @@ -58,75 +60,66 @@ const LeftMainNav = ({ {isAdmin && ( - -
- Search -
- )} - {!isAdmin && ( - -
- Log -
- )} - - -
- Contact -
-
- - {isAdmin ? ( - <> - + <> + +
+ Search +
+ +
- Club + Contact
- - ) : ( - +
Club -
- )} -
- - -
- Logout -
+ + +
+ Logout +
+ + )} + {!isAdmin && ( + <> + +
+ Profile +
+ + )}
diff --git a/frontend/src/components/LeftNav/LeftNav.tsx b/frontend/src/components/LeftNav/LeftNav.tsx index 3ff2ab2d4..6aa1b8334 100644 --- a/frontend/src/components/LeftNav/LeftNav.tsx +++ b/frontend/src/components/LeftNav/LeftNav.tsx @@ -2,10 +2,10 @@ import styled from "styled-components"; import LeftMainNavContainer from "@/components/LeftNav/LeftMainNav/LeftMainNav.container"; import LeftSectionNavContainer from "@/components/LeftNav/LeftSectionNav/LeftSectionNav.container"; -const LeftNav: React.FC<{ isVisible: boolean; isAdmin?: boolean }> = ({ - isAdmin, - isVisible, -}) => { +const LeftNav: React.FC<{ + isVisible: boolean; + isAdmin?: boolean; +}> = ({ isAdmin, isVisible }) => { return ( diff --git a/frontend/src/components/LeftNav/LeftSectionNav/LeftSectionNav.container.tsx b/frontend/src/components/LeftNav/LeftSectionNav/LeftSectionNav.container.tsx index 3a48d4816..93fb42c38 100644 --- a/frontend/src/components/LeftNav/LeftSectionNav/LeftSectionNav.container.tsx +++ b/frontend/src/components/LeftNav/LeftSectionNav/LeftSectionNav.container.tsx @@ -1,3 +1,4 @@ +import { useLocation, useNavigate } from "react-router-dom"; import { useRecoilState, useRecoilValue } from "recoil"; import { currentSectionNameState } from "@/recoil/atoms"; import { currentFloorSectionState } from "@/recoil/selectors"; @@ -9,20 +10,54 @@ const LeftSectionNavContainer = ({ isVisible }: { isVisible: boolean }) => { const [currentFloorSection, setCurrentFloorSection] = useRecoilState( currentSectionNameState ); - + const navigator = useNavigate(); + const { pathname } = useLocation(); const { closeLeftNav } = useMenu(); + const isProfilePage: boolean = location.pathname.includes("profile"); const onClickSection = (section: string) => { closeLeftNav(); setCurrentFloorSection(section); }; + const onClickProfile = () => { + closeLeftNav(); + navigator("profile"); + }; + + const onClickLentLogButton = () => { + closeLeftNav(); + navigator("profile/log"); + }; + + const onClickSlack = () => { + window.open( + "https://42born2code.slack.com/archives/C02V6GE8LD7", + "_blank", + "noopener noreferrer" + ); + }; + + const onClickClubForm = () => { + window.open( + "https://docs.google.com/forms/d/e/1FAIpQLSfp-d7qq8gTvmQe5i6Gtv_mluNSICwuv5pMqeTBqt9NJXXP7w/closedform", + "_blank", + "noopener noreferrer" + ); + }; + return ( ); }; diff --git a/frontend/src/components/LeftNav/LeftSectionNav/LeftSectionNav.tsx b/frontend/src/components/LeftNav/LeftSectionNav/LeftSectionNav.tsx index 65a8d23d9..70ebce5f6 100644 --- a/frontend/src/components/LeftNav/LeftSectionNav/LeftSectionNav.tsx +++ b/frontend/src/components/LeftNav/LeftSectionNav/LeftSectionNav.tsx @@ -6,6 +6,12 @@ interface ILeftSectionNav { onClickSection: Function; currentFloorSection: string; floorSection: string[]; + isProfile: boolean; + onClickProfile: Function; + pathname: string; + onClickLentLogButton: Function; + onClickSlack: Function; + onClickClubForm: Function; } const LeftSectionNav = ({ @@ -13,28 +19,76 @@ const LeftSectionNav = ({ currentFloorSection, onClickSection, floorSection, + isProfile, + onClickProfile, + pathname, + onClickLentLogButton, + onClickSlack, + onClickClubForm, }: ILeftSectionNav) => { return ( - - {floorSection.map((section: string, index: number) => ( + <> + + {floorSection.map((section: string, index: number) => ( + onClickSection(section)} + > + {section} + + ))} + + + + onClickSection(section)} + onClick={() => onClickProfile()} > - {section} + 내 정보 - ))} - - + onClickLentLogButton()} + > + 대여 기록 + +
+ onClickSlack()} + title="슬랙 캐비닛 채널 새창으로 열기" + > + 문의하기 + + + onClickClubForm()} + title="동아리 사물함 사용 신청서 새창으로 열기" + > + 동아리 신청서 + + + + ); }; -const LeftNavOptionStyled = styled.div<{ isVisible: boolean }>` +const LeftNavOptionStyled = styled.div<{ + isVisible: boolean; +}>` display: ${(props) => (props.isVisible ? "block" : "none")}; min-width: 240px; height: 100%; @@ -44,6 +98,26 @@ const LeftNavOptionStyled = styled.div<{ isVisible: boolean }>` position: relative; `; +const ProfileLeftNavOptionStyled = styled.div<{ + isProfile: boolean; +}>` + display: ${(props) => (props.isProfile ? "block" : "none")}; + min-width: 240px; + height: 100%; + padding: 32px 10px; + border-right: 1px solid var(--line-color); + font-weight: 300; + position: relative; + & hr { + width: 80%; + height: 1px; + background-color: #d9d9d9; + border: 0; + margin-top: 20px; + margin-bottom: 20px; + } +`; + const FloorSectionStyled = styled.div` width: 100%; height: 40px; @@ -61,4 +135,31 @@ const FloorSectionStyled = styled.div` } `; +const SectionLinkStyled = styled.div` + width: 100%; + height: 40px; + line-height: 40px; + text-indent: 20px; + margin: 2px 0; + padding-right: 30px; + cursor: pointer; + display: flex; + align-items: center; + color: var(--gray-color); + & img { + width: 15px; + height: 15px; + margin-left: auto; + } + @media (hover: hover) and (pointer: fine) { + &:hover { + color: var(--main-color); + } + &:hover img { + filter: invert(33%) sepia(55%) saturate(3554%) hue-rotate(230deg) + brightness(99%) contrast(107%); + } + } +`; + export default LeftSectionNav; diff --git a/frontend/src/pages/ProfilePage.tsx b/frontend/src/pages/ProfilePage.tsx new file mode 100644 index 000000000..a111bf2d4 --- /dev/null +++ b/frontend/src/pages/ProfilePage.tsx @@ -0,0 +1,18 @@ +import styled from "styled-components"; + +const ProfilePage = () => { + return 내 정보 여기에 넣어주세용; +}; + +const WrapperStyled = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 70px 0; + @media screen and (max-width: 768px) { + padding: 40px 20px; + } +`; + +export default ProfilePage;