Skip to content

Commit 0a4d95f

Browse files
committed
feat: 레이아웃 구현
1 parent 94feeb8 commit 0a4d95f

File tree

6 files changed

+162
-1
lines changed

6 files changed

+162
-1
lines changed

src/layouts/AuthLayout.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Outlet } from "react-router-dom";
2+
3+
function AuthLayout() {
4+
return (
5+
<div className="min-h-screen flex items-center justify-center">
6+
<div className="w-[21.875rem]">
7+
<Outlet />
8+
</div>
9+
</div>
10+
);
11+
}
12+
13+
export default AuthLayout;

src/layouts/Footer.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import EmailIcon from "../assets/logo/envelope.svg";
2+
import FacebookIcon from "../assets/logo/facebook.svg";
3+
import InstagramIcon from "../assets/logo/instagram.svg";
4+
5+
function Footer() {
6+
return (
7+
<footer className="w-full bg-[var(--color-gray-10)] py-6 px-4 gap-2">
8+
<div className="max-w-screen-xl mx-auto flex flex-col sm:flex-row items-center justify-between text-[var(--color-gray-50)] text-base">
9+
<span>©codeit - 2023</span>
10+
11+
<div className="flex gap-6">
12+
<a href="/privacy-policy" className="hover:underline">
13+
Privacy Policy
14+
</a>
15+
<a href="/faq" className="hover:underline">
16+
FAQ
17+
</a>
18+
</div>
19+
20+
<div className="flex gap-4">
21+
<img src={EmailIcon} alt="email" className="w-5 h-5" />
22+
<img src={FacebookIcon} alt="facebook" className="w-5 h-5" />
23+
<img src={InstagramIcon} alt="instagram" className="w-5 h-5" />
24+
</div>
25+
</div>
26+
</footer>
27+
);
28+
}
29+
30+
export default Footer;

src/layouts/Header.tsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Link } from "react-router-dom";
2+
3+
import ActiveAlarmIcon from "../assets/icon/active.svg";
4+
import InActiveAlarmIcon from "../assets/icon/inactive.svg";
5+
import SearchIcon from "../assets/icon/search.svg";
6+
import Logo from "../assets/logo/thejulge.svg";
7+
interface HeaderProps {
8+
isLoggedIn: boolean;
9+
userNavLabel?: string; // "내 가게" or "내 프로필"
10+
hasAlarm?: boolean;
11+
onLogout?: () => void;
12+
onToggleAlarm?: () => void;
13+
}
14+
15+
function Header({
16+
isLoggedIn,
17+
userNavLabel,
18+
hasAlarm,
19+
onLogout,
20+
onToggleAlarm,
21+
}: HeaderProps) {
22+
const userPath = userNavLabel === "내 가게" ? "/shop" : "/profile";
23+
const alarmIcon = hasAlarm ? ActiveAlarmIcon : InActiveAlarmIcon;
24+
25+
return (
26+
<header className="w-full flex justify-between items-center h-[4.375rem] bg-[var(--color-white)]] sm:py-0">
27+
<div className="flex items-center gap-[3.125rem]">
28+
<Link to="/">
29+
<img src={Logo} alt="thejulge" />
30+
</Link>
31+
<div className="relative w-full sm:w-[28.125rem] order-1 sm:order-none bg-[var(--color-gray-10)] border border-transparent rounded-[0.625rem]">
32+
<img
33+
src={SearchIcon}
34+
alt="SearchIcon"
35+
className="absolute inset-y-2.5 left-3 flex items-center"
36+
/>
37+
<input
38+
type="text"
39+
placeholder="가게 이름으로 찾아보세요"
40+
className="pl-10 w-[28.125rem] h-[2.5rem] gap-[0.625rem] rounded-[0.625rem] p-[0.625rem] bg-[var(--color-gray-10)] placeholder:font-normal placeholder:text-[0.875rem] placeholder:leading-[1.375rem] placeholder:tracking-[0%] placeholder:align-middle placeholder:text-[var(--color-gray-40)]"
41+
/>
42+
</div>
43+
</div>
44+
45+
<div className="w-[13.1875rem] h-[1.5rem] flex items-center gap-[2.5rem] font-bold text-[1rem] leading-[1.25rem] tracking-[0%] text-right align-middle text-[var(--color-black)]]">
46+
{isLoggedIn ? (
47+
<>
48+
<Link to={userPath}>{userNavLabel}</Link>
49+
<button onClick={onLogout} className="cursor-pointer">
50+
로그아웃
51+
</button>
52+
<button className="cursor-pointer" onClick={onToggleAlarm}>
53+
<img src={alarmIcon} alt="AlertIcon" />
54+
</button>
55+
</>
56+
) : (
57+
<>
58+
<Link to="/signin">로그인</Link>
59+
<Link to="/signup">회원가입</Link>
60+
</>
61+
)}
62+
</div>
63+
</header>
64+
);
65+
}
66+
67+
export default Header;

src/layouts/MainLayout.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Outlet } from "react-router-dom";
2+
3+
import Footer from "./Footer";
4+
import Header from "./Header";
5+
interface MainLayoutProps {
6+
isLoggedIn: boolean;
7+
userNavLabel?: string; // "내 가게" or "내 프로필"
8+
hasAlarm?: boolean;
9+
onLogout?: () => void;
10+
onToggleAlarm?: () => void;
11+
}
12+
13+
function MainLayout({
14+
isLoggedIn,
15+
userNavLabel,
16+
hasAlarm,
17+
onLogout,
18+
onToggleAlarm,
19+
}: MainLayoutProps) {
20+
return (
21+
<div className="w-full min-h-screen flex flex-col">
22+
<div className="w-full max-w-[90rem] mx-auto flex-1 px-4 sm:px-6 tablet:px-10 pc:px-20">
23+
<Header
24+
isLoggedIn={isLoggedIn}
25+
userNavLabel={userNavLabel}
26+
hasAlarm={hasAlarm}
27+
onLogout={onLogout}
28+
onToggleAlarm={onToggleAlarm}
29+
/>
30+
31+
<main className="flex-1">
32+
<Outlet />
33+
</main>
34+
</div>
35+
36+
<Footer />
37+
</div>
38+
);
39+
}
40+
41+
export default MainLayout;

src/layouts/index.ts

Whitespace-only changes.

tailwind.config.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,17 @@ export default {
55
"./src/**/*.{js,ts,jsx,tsx}", // 모든 소스 코드 대상
66
],
77
theme: {
8-
extend: {},
8+
extend: {
9+
maxWidth: {
10+
"screen-1440": "1440px",
11+
},
12+
screens: {
13+
mobile: { max: "375px" },
14+
tablet: "744px",
15+
pc: "1440px",
16+
},
17+
},
918
},
19+
1020
plugins: [],
1121
};

0 commit comments

Comments
 (0)