헤더 로그인 영역 수정

This commit is contained in:
현성필
2025-11-05 11:04:41 +09:00
parent 563a3f054c
commit b20bb0bcbf
6 changed files with 386 additions and 17 deletions
+245
View File
@@ -3109,6 +3109,251 @@ select.form-control {
transform: translateY(0);
}
}
.auth-group {
display: flex;
align-items: center;
gap: 16px;
}
.auth-group.authenticated {
gap: 0;
}
.login-btn {
display: inline-flex;
align-items: center;
padding: 10px 20px;
color: #1A1A2E;
text-decoration: none;
border: 2px solid #4B9BFF;
border-radius: 50px;
font-weight: 600;
font-size: 14px;
transition: all 0.3s ease;
}
.login-btn:hover {
background: #EFF6FF;
color: #4B9BFF;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(75, 155, 255, 0.1);
}
.user-profile-dropdown {
position: relative;
}
.user-profile-dropdown .user-profile-btn {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 20px;
background: #EFF6FF;
border: 2px solid transparent;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s ease;
font-family: "Pretendard", -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans KR", sans-serif;
font-size: 14px;
}
.user-profile-dropdown .user-profile-btn .user-name {
color: #1A1A2E;
font-weight: 600;
}
.user-profile-dropdown .user-profile-btn i {
color: #64748B;
font-size: 12px;
transition: transform all 0.15s ease;
}
.user-profile-dropdown .user-profile-btn:hover {
background: #FFFFFF;
border-color: #4B9BFF;
box-shadow: 0 4px 12px rgba(75, 155, 255, 0.1);
}
.user-profile-dropdown .user-profile-btn:hover .user-name {
color: #4B9BFF;
}
.user-profile-dropdown .user-profile-btn:hover i {
color: #4B9BFF;
}
.user-profile-dropdown.active .user-profile-btn i {
transform: rotate(180deg);
}
.user-profile-dropdown.active .profile-dropdown-menu {
visibility: visible;
opacity: 1;
transform: translateY(0);
}
.user-profile-dropdown .profile-dropdown-menu {
position: absolute;
top: calc(100% + 12px);
right: 0;
width: 280px;
background: #FFFFFF;
border: 1px solid #E2E8F0;
border-radius: 12px;
box-shadow: 0 16px 40px rgba(75, 155, 255, 0.2);
visibility: hidden;
opacity: 0;
transform: translateY(-10px);
transition: all all 0.3s ease;
z-index: 100;
overflow: hidden;
}
.user-profile-dropdown .profile-header {
padding: 24px;
background: linear-gradient(135deg, #4B9BFF 0%, #2E7FF7 100%);
color: #FFFFFF;
text-align: center;
}
.user-profile-dropdown .profile-header .user-greeting {
margin: 0 0 4px 0;
font-size: 18px;
font-weight: 700;
}
.user-profile-dropdown .profile-header .user-message {
font-size: 12px;
opacity: 0.9;
}
.user-profile-dropdown .profile-menu-list {
list-style: none;
margin: 0;
padding: 8px 0;
}
.user-profile-dropdown .profile-menu-list li {
margin: 0;
}
.user-profile-dropdown .profile-menu-list li a {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 24px;
color: #1A1A2E;
text-decoration: none;
font-size: 14px;
transition: all 0.15s ease;
}
.user-profile-dropdown .profile-menu-list li a i {
width: 20px;
color: #64748B;
font-size: 14px;
}
.user-profile-dropdown .profile-menu-list li a:hover {
background: #EFF6FF;
color: #4B9BFF;
}
.user-profile-dropdown .profile-menu-list li a:hover i {
color: #4B9BFF;
}
.user-profile-dropdown .profile-footer {
padding: 8px 24px 24px;
border-top: 1px solid #E2E8F0;
}
.user-profile-dropdown .profile-footer .logout-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
width: 100%;
padding: 12px;
background: #F8FAFC;
color: #1A1A2E;
text-decoration: none;
border-radius: 8px;
font-weight: 600;
font-size: 14px;
transition: all 0.3s ease;
}
.user-profile-dropdown .profile-footer .logout-btn i {
font-size: 14px;
}
.user-profile-dropdown .profile-footer .logout-btn:hover {
background: #FF6B6B;
color: #FFFFFF;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(75, 155, 255, 0.1);
}
.drawer-user-info {
padding: 24px;
background: linear-gradient(135deg, #4B9BFF 0%, #2E7FF7 100%);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.drawer-user-info .drawer-profile {
display: flex;
align-items: center;
gap: 16px;
}
.drawer-user-info .drawer-profile .profile-avatar {
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
color: #FFFFFF;
}
.drawer-user-info .drawer-profile .profile-avatar i {
font-size: 32px;
}
.drawer-user-info .drawer-profile .profile-info {
flex: 1;
color: #FFFFFF;
}
.drawer-user-info .drawer-profile .profile-info .profile-name {
margin: 0 0 4px 0;
font-size: 18px;
font-weight: 700;
}
.drawer-user-info .drawer-profile .profile-info .profile-greeting {
font-size: 12px;
opacity: 0.9;
}
.drawer-logout-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
width: 100%;
padding: 14px 20px;
background: #FF6B6B;
color: #FFFFFF;
text-decoration: none;
border-radius: 12px;
font-weight: 600;
font-size: 16px;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(75, 155, 255, 0.1);
}
.drawer-logout-btn i {
font-size: 16px;
}
.drawer-logout-btn:hover {
background: #ff3838;
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(75, 155, 255, 0.15);
}
@media (max-width: 768px) {
.user-profile-dropdown .profile-dropdown-menu {
width: 260px;
right: -10px;
}
}
@media (max-width: 480px) {
.user-profile-dropdown .user-profile-btn {
padding: 8px 16px;
}
.user-profile-dropdown .user-profile-btn .user-name {
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.user-profile-dropdown .profile-dropdown-menu {
width: 240px;
right: -20px;
}
}
.hero-section {
position: relative;
padding: 160px 0 100px;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -29,6 +29,7 @@
@import 'components/partners';
@import 'components/cta';
@import 'components/password-popup';
@import 'components/header-auth';
// 5. Page-specific styles
@import 'pages/index';
@@ -24,17 +24,58 @@
<li><a href="#docs" class="nav-link">서비스 소개</a></li>
<li><a href="/apis" class="nav-link">오픈 API</a></li>
<li><a href="#playground" class="nav-link">고객지원</a></li>
<li><a href="#community" class="nav-link">MY</a></li>
<li sec:authorize="isAuthenticated()"><a href="#community" class="nav-link">MY</a></li>
</ul>
</nav>
<div class="header-right">
<button class="search-btn"><i class="fas fa-search"></i></button>
<a th:href="@{/login}" class="login-btn">로그인</a>
<a href="#signup" class="signup-btn">
<span>회원 가입</span>
<i class="fas fa-arrow-right"></i>
</a>
<!-- Login State (Anonymous) -->
<div class="auth-group" sec:authorize="isAnonymous()">
<a th:href="@{/login}" class="login-btn">로그인</a>
<a th:href="@{/signup}" class="signup-btn">
<span>회원 가입</span>
<i class="fas fa-arrow-right"></i>
</a>
</div>
<!-- Logout State (Authenticated) -->
<div class="auth-group authenticated" sec:authorize="isAuthenticated()">
<div class="user-profile-dropdown">
<button class="user-profile-btn">
<span class="user-name">[[${#authentication.principal.userName}]]님</span>
<i class="fas fa-chevron-down"></i>
</button>
<div class="profile-dropdown-menu">
<div class="profile-header">
<p class="user-greeting">[[${#authentication.principal.userName}]]님</p>
<span class="user-message">즐거운 하루 되세요!</span>
</div>
<ul class="profile-menu-list">
<li sec:authorize="hasRole('ROLE_DASHBOARD')">
<a th:href="@{/dashboard}"><i class="fas fa-chart-line"></i>대시보드</a>
</li>
<li sec:authorize="hasRole('ROLE_USER_MANAGER')">
<a th:href="@{/users}"><i class="fas fa-users"></i>이용자 관리</a>
</li>
<li sec:authorize="hasRole('ROLE_APP')">
<a th:href="@{/myapikey}"><i class="fas fa-key"></i>인증 키 관리</a>
</li>
<li sec:authorize="hasRole('ROLE_API_KEY_REQUEST_VIEW')">
<a th:href="@{/myapikey/api_key_request/history}"><i class="fas fa-list"></i>인증키 신청 목록</a>
</li>
<li><a th:href="@{/mypage}"><i class="fas fa-user-circle"></i>내 정보 관리</a></li>
<li><a th:href="@{/change_password}"><i class="fas fa-lock"></i>비밀번호 변경</a></li>
</ul>
<div class="profile-footer">
<a th:href="@{/actionLogout.do}" class="logout-btn">
<i class="fas fa-sign-out-alt"></i>
로그아웃
</a>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -79,30 +120,89 @@
</button>
</div>
<!-- Authenticated User Info (Mobile) -->
<div class="drawer-user-info" sec:authorize="isAuthenticated()">
<div class="drawer-profile">
<div class="profile-avatar">
<i class="fas fa-user-circle"></i>
</div>
<div class="profile-info">
<p class="profile-name">[[${#authentication.principal.userName}]]님</p>
<span class="profile-greeting">즐거운 하루 되세요!</span>
</div>
</div>
</div>
<nav class="drawer-nav">
<ul class="drawer-menu">
<li><a href="#docs" class="drawer-link">서비스 소개</a></li>
<li><a href="/apis" class="drawer-link">오픈 API</a></li>
<li><a href="#playground" class="drawer-link">고객지원</a></li>
<li><a href="#community" class="drawer-link">MY</a></li>
<!-- Authenticated Menu Items -->
<li sec:authorize="isAuthenticated()">
<a href="#community" class="drawer-link">MY</a>
</li>
<li sec:authorize="hasRole('ROLE_DASHBOARD')">
<a th:href="@{/dashboard}" class="drawer-link">
<i class="fas fa-chart-line"></i> 대시보드
</a>
</li>
<li sec:authorize="hasRole('ROLE_USER_MANAGER')">
<a th:href="@{/users}" class="drawer-link">
<i class="fas fa-users"></i> 이용자 관리
</a>
</li>
<li sec:authorize="hasRole('ROLE_APP')">
<a th:href="@{/myapikey}" class="drawer-link">
<i class="fas fa-key"></i> 인증 키 관리
</a>
</li>
<li sec:authorize="hasRole('ROLE_API_KEY_REQUEST_VIEW')">
<a th:href="@{/myapikey/api_key_request/history}" class="drawer-link">
<i class="fas fa-list"></i> 인증키 신청 목록
</a>
</li>
<li sec:authorize="isAuthenticated()">
<a th:href="@{/mypage}" class="drawer-link">
<i class="fas fa-user-circle"></i> 내 정보 관리
</a>
</li>
<li sec:authorize="isAuthenticated()">
<a th:href="@{/change_password}" class="drawer-link">
<i class="fas fa-lock"></i> 비밀번호 변경
</a>
</li>
</ul>
</nav>
<div class="drawer-actions">
<a th:href="@{/login}" class="drawer-login-btn">로그인</a>
<a href="#signup" class="drawer-signup-btn">
<span>회원 가입</span>
<i class="fas fa-arrow-right"></i>
</a>
<!-- Anonymous User Actions -->
<div sec:authorize="isAnonymous()">
<a th:href="@{/login}" class="drawer-login-btn">로그인</a>
<a th:href="@{/signup}" class="drawer-signup-btn">
<span>회원 가입</span>
<i class="fas fa-arrow-right"></i>
</a>
</div>
<!-- Authenticated User Actions -->
<div sec:authorize="isAuthenticated()">
<a th:href="@{/actionLogout.do}" class="drawer-logout-btn">
<i class="fas fa-sign-out-alt"></i>
로그아웃
</a>
</div>
</div>
</div>
</div>
</th:block>
<!-- Mobile Menu JavaScript -->
<!-- Mobile Menu & Dropdown JavaScript -->
<th:block th:fragment="headerScript">
<script>
document.addEventListener('DOMContentLoaded', function() {
// Mobile Drawer
const menuToggle = document.getElementById('mobileMenuToggle');
const drawer = document.getElementById('mobileDrawer');
const drawerClose = document.getElementById('drawerClose');
@@ -126,6 +226,29 @@
document.querySelectorAll('.drawer-link').forEach(link => {
link.addEventListener('click', closeDrawer);
});
// Desktop User Profile Dropdown
const profileBtn = document.querySelector('.user-profile-btn');
const profileDropdown = document.querySelector('.user-profile-dropdown');
if (profileBtn && profileDropdown) {
profileBtn.addEventListener('click', function(e) {
e.stopPropagation();
profileDropdown.classList.toggle('active');
});
// Close dropdown when clicking outside
document.addEventListener('click', function(e) {
if (!profileDropdown.contains(e.target)) {
profileDropdown.classList.remove('active');
}
});
// Prevent dropdown from closing when clicking inside
profileDropdown.addEventListener('click', function(e) {
e.stopPropagation();
});
}
});
</script>
</th:block>