Skip to content

Commit b16bd01

Browse files
committed
design: 메인페이지 로그인상태, 레이아웃 디자인 #5
1 parent 0e92ba9 commit b16bd01

File tree

8 files changed

+212
-2
lines changed

8 files changed

+212
-2
lines changed

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@
1010
"preview": "vite preview"
1111
},
1212
"dependencies": {
13+
"@fullcalendar/core": "^6.1.15",
14+
"@fullcalendar/daygrid": "^6.1.15",
15+
"@fullcalendar/react": "^6.1.15",
1316
"@tailwindcss/vite": "^4.0.6",
1417
"@tanstack/react-query": "^5.66.0",
1518
"axios": "^1.7.9",
1619
"react": "^19.0.0",
1720
"react-dom": "^19.0.0",
1821
"react-router": "^7.1.5",
22+
"tailwind-merge": "^3.0.1",
1923
"tailwindcss": "^4.0.6",
2024
"zustand": "^5.0.3"
2125
},

src/App.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { Route, Routes } from "react-router";
2-
import Main from "./pages/Main";
32
import SignIn from "./pages/SignIn";
43
import SignUp from "./pages/SignUp";
4+
import MainPage from "./pages/MainPage";
5+
import Layout from "./components/layout/Layout";
56

67
const App = () => {
78
return (
89
<Routes>
9-
<Route path="/" element={<Main />} />
1010
<Route path="signIn" element={<SignIn />} />
1111
<Route path="signUp" element={<SignUp />} />
12+
13+
<Route element={<Layout />}>
14+
<Route path="/" element={<MainPage />} />
15+
</Route>
1216
</Routes>
1317
);
1418
};
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { twMerge } from "tailwind-merge";
2+
3+
interface ScheduleBoxProps {
4+
endTime: string; // 마감시간
5+
remainingTime: string; // 남은 시간
6+
scheduleName: string;
7+
projectName: string;
8+
isDeadline?: boolean; // 마감시간 임박 시 true
9+
}
10+
11+
const ScheduleBox = ({
12+
endTime,
13+
remainingTime,
14+
scheduleName,
15+
projectName,
16+
isDeadline = false,
17+
}: ScheduleBoxProps) => {
18+
return (
19+
<div
20+
className={twMerge(
21+
`font-bold w-full h-[80px] flex justify-around flex-shrink-0
22+
items-center px-5 bg-[#a1a1a1] cursor-pointer
23+
${isDeadline && "bg-[#FF7676] text-white"}`
24+
)}
25+
>
26+
{/* 마감시간, 남은시간 */}
27+
<div>
28+
<div className="flex items-center gap-2">
29+
<p className="text-[12px]">마감시간</p>
30+
<p>{endTime}</p>
31+
</div>
32+
33+
<div className="flex items-center gap-2">
34+
<p className="text-[12px]">남은시간</p>
35+
<p>{remainingTime}</p>
36+
</div>
37+
</div>
38+
39+
{/* 업무명, 프로젝트 명 */}
40+
<div>
41+
<p>{scheduleName}</p>
42+
<p>{projectName}</p>
43+
</div>
44+
</div>
45+
);
46+
};
47+
48+
export default ScheduleBox;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { useState } from "react";
2+
import ScheduleBox from "./ScheduleBox";
3+
4+
const TodaySchedule = () => {
5+
// 임시 배열입니다
6+
const [arr, setArr] = useState(Array.from({ length: 20 }, (_, i) => i));
7+
8+
return (
9+
<div
10+
className="w-[450px] bg-red-100 px-5 py-10
11+
flex flex-col gap-10 items-center"
12+
style={{ height: "calc(100vh - 50px)" }}
13+
>
14+
<p className="font-bold text-[26px]">현재 날짜 시간</p>
15+
16+
<div className="w-full flex-1 min-h-0">
17+
<div className="overflow-y-auto w-full h-full flex flex-col gap-2 min-h-0">
18+
{arr.map((_, i) => (
19+
<ScheduleBox
20+
key={i}
21+
endTime="15:00"
22+
remainingTime="40분"
23+
scheduleName="퍼블리싱"
24+
projectName="이룸 프로젝트"
25+
isDeadline={i < 4}
26+
/>
27+
))}
28+
</div>
29+
</div>
30+
</div>
31+
);
32+
};
33+
34+
export default TodaySchedule;

src/components/layout/Header.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { useState } from "react";
2+
import { Link } from "react-router";
3+
4+
const Header = () => {
5+
const [isLogin, setIsLogin] = useState(true);
6+
7+
// 임시 로그인, 로그아웃 버튼
8+
const handleLogin = () => {
9+
setIsLogin((prev) => !prev);
10+
};
11+
return (
12+
<>
13+
<header className="h-[50px] bg-[#d6d6d6] flex items-center px-5 justify-between">
14+
<div>
15+
<h1 className="text-[25px] font-bold">로고</h1>
16+
</div>
17+
18+
<ul className="flex font-bold gap-5">
19+
<li>
20+
<Link to={"/project-room"}>프로젝트룸</Link>
21+
</li>
22+
<li>
23+
<Link to={"/meeting-room"}>미팅룸</Link>
24+
</li>
25+
</ul>
26+
27+
<ul className="flex font-bold gap-3">
28+
<li className="cursor-pointer">다크모드</li>
29+
{isLogin ? (
30+
<>
31+
<li className="cursor-pointer">알람</li>
32+
<li>
33+
<Link to={"/"}>마이페이지</Link>
34+
</li>
35+
<li onClick={handleLogin} className="cursor-pointer">
36+
로그아웃
37+
</li>
38+
</>
39+
) : (
40+
<>
41+
<li>
42+
<Link to={"/"} onClick={handleLogin}>
43+
로그인
44+
</Link>
45+
</li>
46+
<li>
47+
<Link to="/">회원가입</Link>
48+
</li>
49+
</>
50+
)}
51+
</ul>
52+
</header>
53+
</>
54+
);
55+
};
56+
57+
export default Header;

src/components/layout/Layout.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Outlet } from "react-router";
2+
import Header from "./Header";
3+
import Sidebar from "./Sidebar";
4+
5+
const Layout = () => {
6+
return (
7+
<div>
8+
<Header />
9+
<div className="absolute">
10+
<Sidebar />
11+
</div>
12+
<Outlet />
13+
</div>
14+
);
15+
};
16+
17+
export default Layout;

src/components/layout/Sidebar.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const Sidebar = () => {
2+
return (
3+
<div
4+
className="w-[68px] bg-[#a1a1a1]"
5+
style={{ height: "calc(100vh - 50px)" }}
6+
>
7+
<ul className="flex justify-center pt-10">
8+
<li className="font-bold">펴기</li>
9+
</ul>
10+
</div>
11+
);
12+
};
13+
14+
export default Sidebar;

src/pages/MainPage.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import FullCalendar from "@fullcalendar/react";
2+
import dayGridPlugin from "@fullcalendar/daygrid";
3+
import TodaySchedule from "../components/MainPage/TodaySchedule";
4+
5+
const MainPage = () => {
6+
return (
7+
<div
8+
className="px-5 bg-gray-100 flex gap-2"
9+
style={{ height: "calc(100vh - 50px)" }}
10+
>
11+
{/* 캘린더 */}
12+
<div className="flex-1 px-[60px] flex flex-col gap-2">
13+
<div className="flex justify-end">
14+
<ul className="flex gap-2 font-bold">
15+
<li className="bg-[#a1a1a1] px-3 py-1 cursor-pointer">프로젝트</li>
16+
<li className="bg-[#a1a1a1] px-3 py-1 cursor-pointer">개인업무</li>
17+
</ul>
18+
</div>
19+
<FullCalendar
20+
plugins={[dayGridPlugin]}
21+
initialView="dayGridMonth"
22+
height={"calc(100vh - 50px)"}
23+
/>
24+
</div>
25+
26+
{/* 오늘의 일정 */}
27+
<TodaySchedule />
28+
</div>
29+
);
30+
};
31+
32+
export default MainPage;

0 commit comments

Comments
 (0)