Skip to content

Commit 7d91567

Browse files
committed
2 parents 4e15d86 + 261a2ca commit 7d91567

File tree

5 files changed

+171
-4
lines changed

5 files changed

+171
-4
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
@use "@permit/design-system/styles/variables" as theme;
2+
3+
.header {
4+
width: 100%;
5+
6+
background-color: theme.$black;
7+
}
8+
9+
.content {
10+
display: flex;
11+
flex-direction: row;
12+
align-items: center;
13+
justify-content: space-between;
14+
box-sizing: border-box;
15+
width: 100%;
16+
padding: 40px 40px 20px;
17+
18+
// Mobile responsive
19+
@media (max-width: 768px) {
20+
height: 56px;
21+
padding: 14px 16px;
22+
}
23+
}
24+
25+
.logo {
26+
position: relative;
27+
width: 115.43px;
28+
height: 17px;
29+
30+
// Mobile responsive - 데스크톱과 동일한 크기 유지
31+
@media (max-width: 768px) {
32+
width: 115.43px;
33+
height: 17px;
34+
}
35+
}
36+
37+
.logo_image {
38+
width: 100%;
39+
height: 100%;
40+
object-fit: contain;
41+
}
42+
43+
.actions {
44+
display: flex;
45+
flex-direction: row;
46+
gap: 20px;
47+
align-items: center;
48+
49+
// Mobile responsive
50+
@media (max-width: 768px) {
51+
gap: 8px;
52+
}
53+
}
54+
55+
.nav_button {
56+
height: 42px;
57+
padding: 10px 36px;
58+
59+
font-weight: theme.$medium;
60+
font-size: theme.$body-14;
61+
62+
background-color: theme.$gray-700;
63+
border-color: theme.$gray-700;
64+
border-radius: 34px;
65+
66+
transition: theme.$transition-fast;
67+
68+
&:hover {
69+
background-color: theme.$gray-600;
70+
border-color: theme.$gray-600;
71+
}
72+
73+
// Mobile responsive
74+
@media (max-width: 768px) {
75+
height: 34px;
76+
padding: 10px 24px;
77+
78+
border-radius: 34px;
79+
}
80+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"use client";
2+
3+
import { useEffect, useState } from "react";
4+
import Image from "next/image";
5+
import Link from "next/link";
6+
import { usePathname, useRouter } from "next/navigation";
7+
import classNames from "classnames/bind";
8+
import permitLogo from "public/assets/png/permit_logo.png";
9+
10+
import { Button } from "@permit/design-system";
11+
import { useLogoutMutation } from "@/data/users/postUserLogout/mutation";
12+
import { safeLocalStorage } from "@/lib/storage";
13+
import { PATH } from "@/shared/constants/path";
14+
import { IS_LOGINED } from "@/shared/constants/storage";
15+
16+
import styles from "./index.module.scss";
17+
18+
const cx = classNames.bind(styles);
19+
20+
export const Header = () => {
21+
const router = useRouter();
22+
const pathname = usePathname();
23+
24+
const [isLogined, setIsLogined] = useState(false);
25+
26+
const { mutateAsync: mutateLogout } = useLogoutMutation();
27+
28+
useEffect(() => {
29+
try {
30+
const stored = safeLocalStorage.get(IS_LOGINED);
31+
32+
if (stored !== null) {
33+
setIsLogined(JSON.parse(stored));
34+
}
35+
} catch {
36+
// 파싱 실패 시 기본값(false) 유지
37+
}
38+
}, [pathname]);
39+
40+
const handleSignout = async () => {
41+
try {
42+
// TODO: 로그아웃 여부 물어봐야할까?
43+
if (!confirm("로그아웃 하시겠습니까?")) {
44+
return;
45+
}
46+
47+
await mutateLogout();
48+
49+
safeLocalStorage.remove(IS_LOGINED);
50+
window.location.href = `${PATH.LOGIN}?redirectUrl=${encodeURIComponent(pathname)}`;
51+
} catch (error) {
52+
// 로그아웃 에러는 처리하지 않고, 로그인 페이지로 이동
53+
safeLocalStorage.remove(IS_LOGINED);
54+
window.location.href = `${PATH.LOGIN}?redirectUrl=${encodeURIComponent(pathname)}`;
55+
}
56+
};
57+
58+
const onLoginClick = () => {
59+
router.push(`${PATH.LOGIN}?redirectUrl=${encodeURIComponent(pathname)}`);
60+
};
61+
62+
return (
63+
<header className={cx("header")}>
64+
<div className={cx("content")}>
65+
<Link className={cx("logo")} href="/">
66+
<Image src={permitLogo} alt="PERMIT" className={cx("logo_image")} />
67+
</Link>
68+
69+
<div className={cx("actions")}>
70+
<Button
71+
variant="secondary"
72+
size="sm"
73+
className={cx("nav_button")}
74+
onClick={isLogined ? handleSignout : onLoginClick}
75+
>
76+
{isLogined ? "Logout" : "Login"}
77+
</Button>
78+
</div>
79+
</div>
80+
</header>
81+
);
82+
};

apps/ticket/src/app/(pages)/staff/ticket-authorization/_clientBoundary/TicketAuthorizationClient/index.module.scss

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
.container {
44
width: 100%;
5-
min-height: 100vh;
6-
margin-top: 120px;
5+
margin: 40px 0;
76
padding: 24px;
87

98
background-color: theme.$black;
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
import { Header } from "./_clientBoundary/Header";
12
import { TicketAuthorizationClient } from "./_clientBoundary/TicketAuthorizationClient";
23

34
const TicketAuthorizationPage = () => {
4-
return <TicketAuthorizationClient />;
5+
return (
6+
<>
7+
<Header />
8+
<TicketAuthorizationClient />
9+
</>
10+
);
511
};
612

713
export default TicketAuthorizationPage;

apps/ticket/src/shared/components/AuthErrorFallback/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useEffect, useState } from "react";
55
import { LoadingWithLayout } from "../LoadingWithLayout";
66

77
export const AuthErrorFallback = () => {
8-
const [isLoading, setIsLoaidng] = useState(true);
8+
const [isLoading, setIsLoading] = useState(true);
99

1010
useEffect(() => {
1111
const tokenReissue = async () => {

0 commit comments

Comments
 (0)