Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions src/api/auth/logout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 쿠키 삭제 함수
function deleteCookie(name: string, path: string = '/', domain?: string) {
let cookieString = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path};`;

if (domain) {
cookieString += ` domain=${domain};`;
}

document.cookie = cookieString;
}

// 모든 쿠키 삭제 함수
function deleteAllCookies() {
const cookies = document.cookie.split(';');

cookies.forEach(cookie => {
const eqPos = cookie.indexOf('=');
const name = eqPos > -1 ? cookie.substr(0, eqPos).trim() : cookie.trim();

if (name) {
// 다양한 경로와 도메인으로 쿠키 삭제 시도
deleteCookie(name, '/');
deleteCookie(name, '/', window.location.hostname);
deleteCookie(name, '/', `.${window.location.hostname}`);
}
});
}

export async function logout(): Promise<boolean> {
try {
// 모든 쿠키 삭제
deleteAllCookies();

// 세션 스토리지와 로컬 스토리지도 정리
sessionStorage.clear(); // 환영 메시지 플래그도 함께 삭제됨
localStorage.removeItem('currentActivityId'); // 기존에 사용된 로컬스토리지 항목만 삭제

console.log("로그아웃 완료 - 모든 쿠키와 세션 정보가 삭제되었습니다.");
return true;
} catch (err) {
console.error("로그아웃 처리 실패:", err);
return false;
}
}

// 특정 쿠키만 삭제하고 싶을 때 사용
export function logoutWithSpecificCookie(cookieName: string): boolean {
try {
deleteCookie(cookieName);
console.log(`쿠키 '${cookieName}'이(가) 삭제되었습니다.`);
return true;
} catch (err) {
console.error("쿠키 삭제 실패:", err);
return false;
}
}
10 changes: 9 additions & 1 deletion src/api/auth/members.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@ export async function Members(): Promise<boolean> {
const data = await res.json();

if (data.role === "ADMIN") {
alert(`안녕하세요 ${data.name} 관리자님!`);
// 세션 스토리지에서 환영 메시지 표시 여부 확인
const hasShownWelcome = sessionStorage.getItem('hasShownWelcome');

if (!hasShownWelcome) {
alert(`안녕하세요 ${data.name} 관리자님!`);
// 환영 메시지를 표시했다는 것을 세션 스토리지에 저장
sessionStorage.setItem('hasShownWelcome', 'true');
}

return true;
} else {
alert("로그인 실패! 관리자만 접근 가능합니다.");
Expand Down
26 changes: 21 additions & 5 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { IoLogOutOutline } from "react-icons/io5";
import AegisLogo from '../assets/logos/aegis.svg';
import { useNavigate } from "react-router-dom";
import { logout } from '../api/auth/logout';

const Header: React.FC = () => {
const navigate = useNavigate();
Expand All @@ -9,19 +10,34 @@ const Header: React.FC = () => {
navigate("/");
}

const handleLogout = async () => {
if (confirm('로그아웃 하시겠습니까?')) {
const success = await logout();
if (success) {
alert('로그아웃 되었습니다.');
window.location.href = '/login';
} else {
alert('로그아웃 중 오류가 발생했습니다.');
}
}
}

return(
<>
<div className="flex justify-center items-center w-full h-[85px]">
<div className="flex justify-left items-center w-full h-[85px] bg-white"
<div className="fixed top-0 left-0 right-0 z-50 flex justify-center items-center w-full h-[85px] bg-white">
<div className="flex justify-left items-center w-full h-full bg-white cursor-pointer"
onClick={onClick}>
<img className="w-[35px] h-[35px] ml-6" src={AegisLogo} alt="Aegis Logo" />
<p className="ml-4 font-size-20px font-weight-600 color-black">Aegis</p>
</div>
<div className="flex justify-center w-full h-[85px] bg-white"/>
<div className="flex flex-col justify-center items-center h-[85px] bg-white">
<button className="flex items-center justify-center gap-2 w-[111px] h-[43px] rounded-[10px] bg-white border-[1px] border-gray-30 mr-6">
<IoLogOutOutline className="text-[20px]" />
로그아웃
<button
onClick={handleLogout}
className="flex items-center justify-center gap-2 w-[111px] h-[43px] rounded-[10px] bg-white border-[1px] border-gray-30 mr-6 cursor-pointer hover:bg-gray-10"
>
<IoLogOutOutline className="text-[20px]" />
로그아웃
</button>
</div>
</div>
Expand Down
44 changes: 44 additions & 0 deletions src/components/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { NavLink } from "react-router-dom";
import { FiHome } from "react-icons/fi";
import { IoCalendarNumberOutline } from "react-icons/io5";
import { TbRosetteDiscount } from "react-icons/tb";
import { LuBadgeDollarSign } from "react-icons/lu";

const MENU = [
{ to: "/", label: "홈 화면", icon: <FiHome size={18} /> },
{ to: "/event", label: "행사", icon: <IoCalendarNumberOutline size={18} /> },
{ to: "/coupon", label: "쿠폰", icon: <TbRosetteDiscount size={18} /> },
{ to: "/point", label: "포인트", icon: <LuBadgeDollarSign size={18} /> },
];

const Sidebar: React.FC = () => {
return (
<aside
className="fixed left-0 top-[85px] bottom-0 z-40 w-[220px] bg-white">
<ul className="space-y-1">
{MENU.map((item) => (
<li key={item.to}>
<NavLink
to={item.to}
end={item.to === "/"}
className={({ isActive }) =>
`
flex items-center gap-3 w-full px-3 h-11
transition-colors
${isActive
? "bg-[#F2F3F8] text-black"
: "text-black hover:bg-gray-50"}
`
}
>
<span className="shrink-0">{item.icon}</span>
<span className="truncate">{item.label}</span>
</NavLink>
</li>
))}
</ul>
</aside>
);
};

export default Sidebar;
19 changes: 14 additions & 5 deletions src/page/event.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import EventTable from "../components/EventTable";
import Header from "../components/Header";
import Sidebar from '../components/SideBar';
import SearchBar from "../components/Search";
import { useAuthGuard } from '../hooks/useAuthGuard';
import { GetActivities, type Activity } from '../api/activity/get-activities';
Expand Down Expand Up @@ -56,11 +57,19 @@ const Event: React.FC = () => {
};

return(
<> <Header />
<div className="flex flex-col min-h-screen w-full mt-20 px-8">
<div className="flex flex-col gap-6">
<SearchBar/>
<EventTable rows={tableRows} setRows={updateTableRows} />
<>
<Header />
<div className="flex min-h-screen pt-[85px]">
<Sidebar />
<div className="flex-1 flex flex-col items-center justify-center py-6 px-8 ml-60">
<div className="flex flex-col gap-6 w-full max-w-none">
<div className="flex justify-center">
<SearchBar/>
</div>
<div className="flex justify-center">
<EventTable rows={tableRows} setRows={updateTableRows} />
</div>
</div>
</div>
</div>
</>
Expand Down
6 changes: 4 additions & 2 deletions src/page/home.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Header from "../components/Header";
import Sidebar from "../components/SideBar";
import { useAuthGuard } from '../hooks/useAuthGuard';

const Home: React.FC = () => {
Expand All @@ -18,8 +19,9 @@ const Home: React.FC = () => {

return(
<>
<div className="flex flex-col items-center justify-center min-h-screen">
<Header />
<Header />
<div className="flex flex-col items-center justify-center min-h-screen pt-[85px]">
<Sidebar />
</div>
</>
)
Expand Down
Loading