refactor(tkqc): UI 스타일 통일 + 일일공수 제거 + 메뉴 정리

- UI: tkuser 스타일로 통일 (dark slate 헤더, flat 배경, gradient/glass 제거)
- tkqc-common.css 공통 스타일시트 신규 생성
- 의견 제시 API 별도 엔드포인트 추가 (모든 사용자 접근 가능)
- 일일 공수 기능 완전 제거 (라우터, 모델, 스키마, DB 테이블 DROP)
- 프로젝트 관리/사용자 관리 메뉴 숨김 (통합관리 페이지로 이관)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-02-13 10:43:37 +09:00
parent ce270b9e4a
commit c52734154f
26 changed files with 294 additions and 782 deletions

View File

@@ -32,8 +32,8 @@ class CommonHeader {
icon: 'fas fa-chart-line',
url: '/issues-dashboard.html',
pageName: 'issues_dashboard',
color: 'text-slate-600',
bgColor: 'text-slate-600 hover:bg-slate-100'
color: 'text-slate-300',
bgColor: 'text-slate-300 hover:bg-slate-700'
},
{
id: 'issues_inbox',
@@ -41,8 +41,8 @@ class CommonHeader {
icon: 'fas fa-inbox',
url: '/issues-inbox.html',
pageName: 'issues_inbox',
color: 'text-slate-600',
bgColor: 'text-slate-600 hover:bg-slate-100'
color: 'text-slate-300',
bgColor: 'text-slate-300 hover:bg-slate-700'
},
{
id: 'issues_management',
@@ -50,8 +50,8 @@ class CommonHeader {
icon: 'fas fa-cog',
url: '/issues-management.html',
pageName: 'issues_management',
color: 'text-slate-600',
bgColor: 'text-slate-600 hover:bg-slate-100'
color: 'text-slate-300',
bgColor: 'text-slate-300 hover:bg-slate-700'
},
{
id: 'issues_archive',
@@ -59,17 +59,8 @@ class CommonHeader {
icon: 'fas fa-archive',
url: '/issues-archive.html',
pageName: 'issues_archive',
color: 'text-slate-600',
bgColor: 'text-slate-600 hover:bg-slate-100'
},
{
id: 'daily_work',
title: '일일 공수',
icon: 'fas fa-calendar-check',
url: '/daily-work.html',
pageName: 'daily_work',
color: 'text-slate-600',
bgColor: 'text-slate-600 hover:bg-slate-100'
color: 'text-slate-300',
bgColor: 'text-slate-300 hover:bg-slate-700'
},
{
id: 'reports',
@@ -77,8 +68,8 @@ class CommonHeader {
icon: 'fas fa-chart-bar',
url: '/reports.html',
pageName: 'reports',
color: 'text-slate-600',
bgColor: 'text-slate-600 hover:bg-slate-100',
color: 'text-slate-300',
bgColor: 'text-slate-300 hover:bg-slate-700',
subMenus: [
{
id: 'reports_daily',
@@ -86,7 +77,7 @@ class CommonHeader {
icon: 'fas fa-file-excel',
url: '/reports-daily.html',
pageName: 'reports_daily',
color: 'text-slate-600'
color: 'text-slate-300'
},
{
id: 'reports_weekly',
@@ -94,7 +85,7 @@ class CommonHeader {
icon: 'fas fa-calendar-week',
url: '/reports-weekly.html',
pageName: 'reports_weekly',
color: 'text-slate-600'
color: 'text-slate-300'
},
{
id: 'reports_monthly',
@@ -102,29 +93,10 @@ class CommonHeader {
icon: 'fas fa-calendar-alt',
url: '/reports-monthly.html',
pageName: 'reports_monthly',
color: 'text-slate-600'
color: 'text-slate-300'
}
]
},
{
id: 'projects_manage',
title: '프로젝트 관리',
icon: 'fas fa-folder-open',
url: '/project-management.html',
pageName: 'projects_manage',
color: 'text-slate-600',
bgColor: 'text-slate-600 hover:bg-slate-100'
},
{
id: 'users_manage',
title: '사용자 관리',
icon: 'fas fa-users-cog',
url: this._getUserManageUrl(),
pageName: 'users_manage',
color: 'text-slate-600',
bgColor: 'text-slate-600 hover:bg-slate-100',
external: true
}
];
}
@@ -205,14 +177,14 @@ class CommonHeader {
const userRole = this.getUserRoleDisplay();
return `
<header class="bg-white shadow-sm border-b sticky top-0 z-50">
<header class="bg-slate-800 text-white sticky top-0 z-50">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center h-16">
<div class="flex justify-between items-center h-14">
<!-- 로고 및 제목 -->
<div class="flex items-center">
<div class="flex-shrink-0 flex items-center">
<i class="fas fa-shield-halved text-2xl text-slate-700 mr-3"></i>
<h1 class="text-xl font-bold text-gray-900">부적합 관리</h1>
<i class="fas fa-shield-halved text-2xl text-slate-300 mr-3"></i>
<h1 class="text-xl font-bold text-white">부적합 관리</h1>
</div>
</div>
@@ -226,8 +198,8 @@ class CommonHeader {
<!-- 사용자 정보 -->
<div class="flex items-center space-x-3">
<div class="text-right">
<div class="text-sm font-medium text-gray-900">${userDisplayName}</div>
<div class="text-xs text-gray-500">${userRole}</div>
<div class="text-sm font-medium text-white">${userDisplayName}</div>
<div class="text-xs text-slate-400">${userRole}</div>
</div>
<div class="w-8 h-8 bg-slate-600 rounded-full flex items-center justify-center">
<span class="text-white text-sm font-semibold">
@@ -238,7 +210,7 @@ class CommonHeader {
<!-- 드롭다운 메뉴 -->
<div class="relative">
<button id="user-menu-button" class="p-2 text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 rounded-md">
<button id="user-menu-button" class="p-2 text-slate-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2 focus:ring-offset-slate-800 rounded-md">
<i class="fas fa-chevron-down"></i>
</button>
<div id="user-menu" class="hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-1 ring-1 ring-black ring-opacity-5">
@@ -252,14 +224,14 @@ class CommonHeader {
</div>
<!-- 모바일 메뉴 버튼 -->
<button id="mobile-menu-button" class="md:hidden p-2 text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 rounded-md">
<button id="mobile-menu-button" class="md:hidden p-2 text-slate-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2 focus:ring-offset-slate-800 rounded-md">
<i class="fas fa-bars"></i>
</button>
</div>
</div>
<!-- 모바일 메뉴 -->
<div id="mobile-menu" class="md:hidden hidden border-t border-gray-200 py-3">
<div id="mobile-menu" class="md:hidden hidden border-t border-slate-700 py-3">
<div class="space-y-1">
${accessibleMenus.map(menu => this.generateMobileMenuItemHTML(menu)).join('')}
</div>
@@ -370,7 +342,7 @@ class CommonHeader {
*/
generateMobileMenuItemHTML(menu) {
const isActive = this.currentPage === menu.id;
const activeClass = isActive ? 'bg-slate-100 text-slate-800 border-slate-600' : 'text-gray-700 hover:bg-gray-50';
const activeClass = isActive ? 'bg-slate-700 text-white border-white' : 'text-slate-300 hover:bg-slate-700';
// 하위 메뉴가 있는 경우
if (menu.accessibleSubMenus && menu.accessibleSubMenus.length > 0) {
@@ -390,7 +362,7 @@ class CommonHeader {
<div class="hidden ml-6 mt-1 space-y-1">
${menu.accessibleSubMenus.map(subMenu => `
<a href="${subMenu.url}"
class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-gray-600 hover:bg-slate-100 ${this.currentPage === subMenu.id ? 'bg-slate-100 text-slate-800' : ''}"
class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-slate-400 hover:bg-slate-700 hover:text-white ${this.currentPage === subMenu.id ? 'bg-slate-700 text-white' : ''}"
data-page="${subMenu.id}"
onclick="CommonHeader.navigateToPage(event, '${subMenu.url}', '${subMenu.id}')">
<i class="${subMenu.icon} mr-3 ${subMenu.color}"></i>
@@ -491,7 +463,7 @@ class CommonHeader {
loader.className = 'fixed inset-0 bg-white bg-opacity-75 flex items-center justify-center z-50';
loader.innerHTML = `
<div class="text-center">
<div class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
<div class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-slate-600"></div>
<p class="mt-2 text-sm text-gray-600">페이지를 로드하는 중...</p>
</div>
`;
@@ -515,7 +487,7 @@ class CommonHeader {
<div class="bg-white rounded-xl p-6 w-96 max-w-md mx-4 shadow-2xl">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold text-gray-800">
<i class="fas fa-key mr-2 text-blue-500"></i>비밀번호 변경
<i class="fas fa-key mr-2 text-slate-500"></i>비밀번호 변경
</h3>
<button onclick="CommonHeader.hidePasswordModal()" class="text-gray-400 hover:text-gray-600 transition-colors">
<i class="fas fa-times text-lg"></i>
@@ -526,21 +498,21 @@ class CommonHeader {
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">현재 비밀번호</label>
<input type="password" id="currentPasswordInput"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-slate-500 focus:border-slate-500"
required placeholder="현재 비밀번호를 입력하세요">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">새 비밀번호</label>
<input type="password" id="newPasswordInput"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-slate-500 focus:border-slate-500"
required minlength="6" placeholder="새 비밀번호 (최소 6자)">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">새 비밀번호 확인</label>
<input type="password" id="confirmPasswordInput"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-slate-500 focus:border-slate-500"
required placeholder="새 비밀번호를 다시 입력하세요">
</div>
@@ -550,7 +522,7 @@ class CommonHeader {
취소
</button>
<button type="submit"
class="flex-1 px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
class="flex-1 px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-800 transition-colors">
<i class="fas fa-save mr-1"></i>변경
</button>
</div>
@@ -683,10 +655,10 @@ class CommonHeader {
const itemPageId = item.getAttribute('data-page');
if (itemPageId === pageId) {
item.classList.add('bg-slate-700', 'text-white');
item.classList.remove('text-slate-600', 'hover:bg-slate-100');
item.classList.remove('text-slate-300', 'hover:bg-slate-700');
} else {
item.classList.remove('bg-slate-700', 'text-white');
item.classList.add('text-slate-600');
item.classList.add('text-slate-300');
}
});
}