feat(web-ui): Refactor web-ui for improved maintainability and modularity
This commit introduces a series of refactoring changes to the web-ui to remove hardcoded values and improve page integration. - **Centralized Configuration:** Created to centralize API ports, paths, and navigation URLs, replacing hardcoded values across multiple files. - **Modular Component Loading:** Introduced to handle dynamic loading of common HTML components (e.g., sidebar, navbar), using paths from . - **Modular Navigation:** Created to centralize page redirection logic, improving maintainability and reducing direct manipulations. - **Refactored Existing Modules:** Updated , , , and to utilize the new , , and modules. - **ES6 Module Compatibility:** Ensured loads scripts as ES6 modules () to support statements.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
// js/load-navbar.js
|
||||
// 브라우저 호환 버전 - ES6 모듈 제거
|
||||
// /js/load-navbar.js
|
||||
import { getUser, clearAuthData } from './auth.js';
|
||||
import { loadComponent } from './component-loader.js';
|
||||
import { config } from './config.js';
|
||||
|
||||
// 역할 이름을 한글로 변환하는 맵
|
||||
const ROLE_NAMES = {
|
||||
@@ -11,6 +13,21 @@ const ROLE_NAMES = {
|
||||
default: '사용자',
|
||||
};
|
||||
|
||||
/**
|
||||
* 네비게이션 바 DOM을 사용자 정보와 역할에 맞게 수정하는 프로세서입니다.
|
||||
* @param {Document} doc - 파싱된 HTML 문서 객체
|
||||
*/
|
||||
function processNavbarDom(doc) {
|
||||
const currentUser = getUser();
|
||||
if (!currentUser) return;
|
||||
|
||||
// 1. 역할 기반 메뉴 필터링
|
||||
filterMenuByRole(doc, currentUser.role);
|
||||
|
||||
// 2. 사용자 정보 채우기
|
||||
populateUserInfo(doc, currentUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 역할에 따라 메뉴 항목을 필터링합니다.
|
||||
* @param {Document} doc - 파싱된 HTML 문서 객체
|
||||
@@ -24,8 +41,7 @@ function filterMenuByRole(doc, userRole) {
|
||||
];
|
||||
|
||||
selectors.forEach(({ role, selector }) => {
|
||||
// 사용자가 해당 역할을 가지고 있지 않으면 메뉴 항목을 제거
|
||||
if (userRole !== role && userRole !== 'system') { // system 권한도 admin 메뉴 접근 가능
|
||||
if (userRole !== role && userRole !== 'system') {
|
||||
doc.querySelectorAll(selector).forEach(el => el.remove());
|
||||
}
|
||||
});
|
||||
@@ -40,25 +56,18 @@ 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 elements = {
|
||||
'user-name': displayName,
|
||||
'user-role': roleName,
|
||||
'dropdown-user-fullname': displayName,
|
||||
'dropdown-user-id': `@${user.username}`,
|
||||
};
|
||||
|
||||
// 상단 바 사용자 역할
|
||||
const userRoleEl = doc.getElementById('user-role');
|
||||
if (userRoleEl) userRoleEl.textContent = roleName;
|
||||
for (const id in elements) {
|
||||
const el = doc.getElementById(id);
|
||||
if (el) el.textContent = elements[id];
|
||||
}
|
||||
|
||||
// 드롭다운 메뉴 사용자 이름
|
||||
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 버튼 제거됨
|
||||
|
||||
// System 버튼 표시 여부 결정 (system 권한만)
|
||||
const systemBtn = doc.getElementById('systemBtn');
|
||||
if (systemBtn && user.role === 'system') {
|
||||
systemBtn.style.display = 'flex';
|
||||
@@ -72,7 +81,6 @@ 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();
|
||||
@@ -81,36 +89,30 @@ function setupNavbarEvents() {
|
||||
});
|
||||
}
|
||||
|
||||
// 로그아웃 버튼
|
||||
const logoutButton = document.getElementById('dropdown-logout');
|
||||
if (logoutButton) {
|
||||
logoutButton.addEventListener('click', () => {
|
||||
if (confirm('로그아웃 하시겠습니까?')) {
|
||||
clearAuthData();
|
||||
window.location.href = '/index.html';
|
||||
window.location.href = config.paths.loginPage;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Admin 버튼 제거됨
|
||||
|
||||
// System 버튼 클릭 이벤트
|
||||
const systemButton = document.getElementById('systemBtn');
|
||||
if (systemButton) {
|
||||
systemButton.addEventListener('click', () => {
|
||||
window.location.href = '/pages/dashboard/system.html';
|
||||
window.location.href = config.paths.systemDashboard;
|
||||
});
|
||||
}
|
||||
|
||||
// Dashboard 버튼 클릭 이벤트
|
||||
const dashboardButton = document.querySelector('.dashboard-btn');
|
||||
if (dashboardButton) {
|
||||
dashboardButton.addEventListener('click', () => {
|
||||
window.location.href = '/pages/dashboard/group-leader.html';
|
||||
window.location.href = config.paths.groupLeaderDashboard;
|
||||
});
|
||||
}
|
||||
|
||||
// 외부 클릭 시 드롭다운 닫기
|
||||
document.addEventListener('click', (e) => {
|
||||
if (profileDropdownMenu && !userInfoDropdown.contains(e.target) && !profileDropdownMenu.contains(e.target)) {
|
||||
profileDropdownMenu.classList.remove('show');
|
||||
@@ -130,41 +132,17 @@ function updateTime() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 메인 로직: 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에 삽입된 후에 이벤트 리스너 설정
|
||||
if (getUser()) {
|
||||
// 1. 컴포넌트 로드 및 DOM 수정
|
||||
await loadComponent('navbar', '#navbar-container', processNavbarDom);
|
||||
|
||||
// 2. DOM에 삽입된 후에 이벤트 리스너 설정
|
||||
setupNavbarEvents();
|
||||
|
||||
// 5. 실시간 시간 업데이트 시작
|
||||
// 3. 실시간 시간 업데이트 시작
|
||||
updateTime();
|
||||
setInterval(updateTime, 1000);
|
||||
|
||||
console.log('✅ 네비게이션 바 로딩 완료');
|
||||
|
||||
} catch (error) {
|
||||
console.error('🔴 네비게이션 바 로딩 중 오류 발생:', error);
|
||||
navbarContainer.innerHTML = '<p>네비게이션 바를 불러오는 데 실패했습니다.</p>';
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user