- 삭제된 DB 테이블들과 관련 코드 정리: * 12개 사용하지 않는 테이블 삭제 (activity_logs, CuttingPlan, DailyIssueReports 등) * 관련 모델, 컨트롤러, 라우트 파일들 삭제 * index.js에서 삭제된 라우트들 제거 - 웹 UI 페이지 정리: * 21개 사용하지 않는 페이지 삭제 * issue-reports 폴더 전체 삭제 * 모든 사용자 권한을 그룹장 대시보드로 통일 - 데이터베이스 스키마 정리: * v1 스키마로 통일 (daily_work_reports 테이블) * JSON 데이터 임포트 스크립트 구현 * 외래키 관계 정리 및 데이터 일관성 확보 - 통합 Docker Compose 설정: * 모든 서비스를 단일 docker-compose.yml로 통합 * 20000번대 포트 유지 * JWT 시크릿 및 환경변수 설정 - 문서화: * DATABASE_SCHEMA.md: 현재 DB 스키마 문서화 * DELETED_TABLES.md: 삭제된 테이블 목록 * DELETED_PAGES.md: 삭제된 페이지 목록
172 lines
5.4 KiB
JavaScript
172 lines
5.4 KiB
JavaScript
// js/load-navbar.js
|
|
import { getUser, clearAuthData } from './auth.js';
|
|
|
|
// 역할 이름을 한글로 변환하는 맵
|
|
const ROLE_NAMES = {
|
|
admin: '관리자',
|
|
system: '시스템 관리자',
|
|
leader: '그룹장',
|
|
user: '작업자',
|
|
support: '지원팀',
|
|
default: '사용자',
|
|
};
|
|
|
|
/**
|
|
* 사용자 역할에 따라 메뉴 항목을 필터링합니다.
|
|
* @param {Document} doc - 파싱된 HTML 문서 객체
|
|
* @param {string} userRole - 현재 사용자의 역할
|
|
*/
|
|
function filterMenuByRole(doc, userRole) {
|
|
const selectors = [
|
|
{ role: 'admin', selector: '.admin-only' },
|
|
{ role: 'system', selector: '.system-only' },
|
|
{ role: 'leader', selector: '.leader-only' },
|
|
];
|
|
|
|
selectors.forEach(({ role, selector }) => {
|
|
// 사용자가 해당 역할을 가지고 있지 않으면 메뉴 항목을 제거
|
|
if (userRole !== role) {
|
|
doc.querySelectorAll(selector).forEach(el => el.remove());
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 네비게이션 바에 사용자 정보를 채웁니다.
|
|
* @param {Document} doc - 파싱된 HTML 문서 객체
|
|
* @param {object} user - 현재 사용자 객체
|
|
*/
|
|
function populateUserInfo(doc, user) {
|
|
const displayName = user.name || user.username;
|
|
const roleName = ROLE_NAMES[user.role] || ROLE_NAMES.default;
|
|
|
|
// 상단 바 사용자 이름
|
|
const userNameEl = doc.getElementById('user-name');
|
|
if (userNameEl) userNameEl.textContent = displayName;
|
|
|
|
// 상단 바 사용자 역할
|
|
const userRoleEl = doc.getElementById('user-role');
|
|
if (userRoleEl) userRoleEl.textContent = roleName;
|
|
|
|
// 드롭다운 메뉴 사용자 이름
|
|
const dropdownNameEl = doc.getElementById('dropdown-user-fullname');
|
|
if (dropdownNameEl) dropdownNameEl.textContent = displayName;
|
|
|
|
// 드롭다운 메뉴 사용자 아이디
|
|
const dropdownIdEl = doc.getElementById('dropdown-user-id');
|
|
if (dropdownIdEl) dropdownIdEl.textContent = `@${user.username}`;
|
|
|
|
// Admin 버튼 표시 여부 결정 (admin 권한만)
|
|
const adminBtn = doc.getElementById('adminBtn');
|
|
if (adminBtn && user.role === 'admin') {
|
|
adminBtn.style.display = 'flex';
|
|
}
|
|
|
|
// System 버튼 표시 여부 결정 (system 권한만)
|
|
const systemBtn = doc.getElementById('systemBtn');
|
|
if (systemBtn && user.role === 'system') {
|
|
systemBtn.style.display = 'flex';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 네비게이션 바와 관련된 모든 이벤트를 설정합니다.
|
|
*/
|
|
function setupNavbarEvents() {
|
|
const userInfoDropdown = document.getElementById('user-info-dropdown');
|
|
const profileDropdownMenu = document.getElementById('profile-dropdown-menu');
|
|
|
|
// 드롭다운 토글
|
|
if (userInfoDropdown && profileDropdownMenu) {
|
|
userInfoDropdown.addEventListener('click', (e) => {
|
|
e.stopPropagation();
|
|
profileDropdownMenu.classList.toggle('show');
|
|
userInfoDropdown.classList.toggle('active');
|
|
});
|
|
}
|
|
|
|
// 로그아웃 버튼
|
|
const logoutButton = document.getElementById('dropdown-logout');
|
|
if (logoutButton) {
|
|
logoutButton.addEventListener('click', () => {
|
|
if (confirm('로그아웃 하시겠습니까?')) {
|
|
clearAuthData();
|
|
window.location.href = '/index.html';
|
|
}
|
|
});
|
|
}
|
|
|
|
// Admin 버튼 클릭 이벤트
|
|
const adminButton = document.getElementById('adminBtn');
|
|
if (adminButton) {
|
|
adminButton.addEventListener('click', () => {
|
|
window.location.href = '/pages/dashboard/admin.html';
|
|
});
|
|
}
|
|
|
|
// System 버튼 클릭 이벤트
|
|
const systemButton = document.getElementById('systemBtn');
|
|
if (systemButton) {
|
|
systemButton.addEventListener('click', () => {
|
|
window.location.href = '/pages/dashboard/system.html';
|
|
});
|
|
}
|
|
|
|
// 외부 클릭 시 드롭다운 닫기
|
|
document.addEventListener('click', (e) => {
|
|
if (profileDropdownMenu && !userInfoDropdown.contains(e.target) && !profileDropdownMenu.contains(e.target)) {
|
|
profileDropdownMenu.classList.remove('show');
|
|
userInfoDropdown.classList.remove('active');
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 현재 시간을 업데이트하는 함수
|
|
*/
|
|
function updateTime() {
|
|
const timeElement = document.getElementById('current-time');
|
|
if (timeElement) {
|
|
const now = new Date();
|
|
timeElement.textContent = now.toLocaleTimeString('ko-KR', { hour12: false });
|
|
}
|
|
}
|
|
|
|
|
|
// 메인 로직: DOMContentLoaded 시 실행
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
const navbarContainer = document.getElementById('navbar-container');
|
|
if (!navbarContainer) return;
|
|
|
|
const currentUser = getUser();
|
|
if (!currentUser) return; // 사용자가 없으면 아무 작업도 하지 않음
|
|
|
|
try {
|
|
const response = await fetch('/components/navbar.html');
|
|
const htmlText = await response.text();
|
|
|
|
// 1. 텍스트를 가상 DOM으로 파싱
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(htmlText, 'text/html');
|
|
|
|
// 2. DOM에 삽입하기 *전*에 내용 수정
|
|
filterMenuByRole(doc, currentUser.role);
|
|
populateUserInfo(doc, currentUser);
|
|
|
|
// 3. 수정 완료된 HTML을 실제 DOM에 삽입 (깜빡임 방지)
|
|
navbarContainer.innerHTML = doc.body.innerHTML;
|
|
|
|
// 4. DOM에 삽입된 후에 이벤트 리스너 설정
|
|
setupNavbarEvents();
|
|
|
|
// 5. 실시간 시간 업데이트 시작
|
|
updateTime();
|
|
setInterval(updateTime, 1000);
|
|
|
|
console.log('✅ 네비게이션 바 로딩 완료');
|
|
|
|
} catch (error) {
|
|
console.error('🔴 네비게이션 바 로딩 중 오류 발생:', error);
|
|
navbarContainer.innerHTML = '<p>네비게이션 바를 불러오는 데 실패했습니다.</p>';
|
|
}
|
|
}); |