- 실시간 작업장 현황을 지도로 시각화 - 작업장 관리 페이지에서 정의한 구역 정보 활용 - TBM 작업자 및 방문자 현황 표시 주요 변경사항: - dashboard.html: 작업장 현황 섹션 추가 (기존 작업 현황 테이블 제거) - workplace-status.js: 지도 렌더링 및 데이터 통합 로직 구현 - modern-dashboard.js: 삭제된 DOM 요소 조건부 체크 추가 시각화 방식: - 인원 없음: 회색 테두리 + 작업장 이름 - 내부 작업자: 파란색 영역 + 인원 수 - 외부 방문자: 보라색 영역 + 인원 수 - 둘 다: 초록색 영역 + 총 인원 수 기술 구현: - Canvas API 기반 사각형 영역 렌더링 - map-regions API를 통한 데이터 일관성 보장 - 클릭 이벤트로 상세 정보 모달 표시 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
179 lines
5.2 KiB
JavaScript
179 lines
5.2 KiB
JavaScript
// /js/load-navbar.js
|
|
import { getUser, clearAuthData } from './auth.js';
|
|
import { loadComponent } from './component-loader.js';
|
|
import { config } from './config.js';
|
|
|
|
// 역할 이름을 한글로 변환하는 맵
|
|
const ROLE_NAMES = {
|
|
admin: '관리자',
|
|
system: '시스템 관리자',
|
|
leader: '그룹장',
|
|
user: '작업자',
|
|
support: '지원팀',
|
|
default: '사용자',
|
|
};
|
|
|
|
/**
|
|
* 네비게이션 바 DOM을 사용자 정보와 역할에 맞게 수정하는 프로세서입니다.
|
|
* @param {Document} doc - 파싱된 HTML 문서 객체
|
|
*/
|
|
async function processNavbarDom(doc) {
|
|
const currentUser = getUser();
|
|
if (!currentUser) return;
|
|
|
|
// 1. 역할 및 페이지 권한 기반 메뉴 필터링
|
|
await filterMenuByPageAccess(doc, currentUser);
|
|
|
|
// 2. 사용자 정보 채우기
|
|
populateUserInfo(doc, currentUser);
|
|
}
|
|
|
|
/**
|
|
* 사용자의 페이지 접근 권한에 따라 메뉴 항목을 필터링합니다.
|
|
* @param {Document} doc - 파싱된 HTML 문서 객체
|
|
* @param {object} currentUser - 현재 사용자 객체
|
|
*/
|
|
async function filterMenuByPageAccess(doc, currentUser) {
|
|
const userRole = (currentUser.role || '').toLowerCase();
|
|
|
|
// Admin은 모든 메뉴 표시
|
|
if (userRole === 'admin' || userRole === 'system') {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// 사용자의 페이지 접근 권한 조회
|
|
const cached = localStorage.getItem('userPageAccess');
|
|
let accessiblePages = null;
|
|
|
|
if (cached) {
|
|
const cacheData = JSON.parse(cached);
|
|
// 캐시가 5분 이내인 경우 사용
|
|
if (Date.now() - cacheData.timestamp < 5 * 60 * 1000) {
|
|
accessiblePages = cacheData.pages;
|
|
}
|
|
}
|
|
|
|
// 캐시가 없으면 API 호출
|
|
if (!accessiblePages) {
|
|
const response = await fetch(`${window.API_BASE_URL}/api/users/${currentUser.user_id}/page-access`, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
|
}
|
|
});
|
|
|
|
if (!response.ok) {
|
|
console.error('페이지 권한 조회 실패:', response.status);
|
|
return;
|
|
}
|
|
|
|
const data = await response.json();
|
|
accessiblePages = data.data.pageAccess || [];
|
|
|
|
// 캐시 저장
|
|
localStorage.setItem('userPageAccess', JSON.stringify({
|
|
pages: accessiblePages,
|
|
timestamp: Date.now()
|
|
}));
|
|
}
|
|
|
|
// 접근 가능한 페이지 키 목록
|
|
const accessiblePageKeys = accessiblePages
|
|
.filter(p => p.can_access === 1)
|
|
.map(p => p.page_key);
|
|
|
|
// 메뉴 항목에 data-page-key 속성이 있으면 해당 권한 체크
|
|
const menuItems = doc.querySelectorAll('[data-page-key]');
|
|
menuItems.forEach(item => {
|
|
const pageKey = item.getAttribute('data-page-key');
|
|
|
|
// 대시보드와 프로필 페이지는 모든 사용자 접근 가능
|
|
if (pageKey === 'dashboard' || pageKey.startsWith('profile.')) {
|
|
return;
|
|
}
|
|
|
|
// 권한이 없으면 메뉴 항목 제거
|
|
if (!accessiblePageKeys.includes(pageKey)) {
|
|
item.remove();
|
|
}
|
|
});
|
|
|
|
// Admin 전용 메뉴는 무조건 제거
|
|
doc.querySelectorAll('.admin-only').forEach(el => el.remove());
|
|
|
|
} catch (error) {
|
|
console.error('메뉴 필터링 오류:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 네비게이션 바에 사용자 정보를 채웁니다.
|
|
* @param {Document} doc - 파싱된 HTML 문서 객체
|
|
* @param {object} user - 현재 사용자 객체
|
|
*/
|
|
function populateUserInfo(doc, user) {
|
|
const displayName = user.name || user.username;
|
|
// 대소문자 구분 없이 처리
|
|
const roleLower = (user.role || '').toLowerCase();
|
|
const roleName = ROLE_NAMES[roleLower] || ROLE_NAMES.default;
|
|
|
|
const elements = {
|
|
'userName': displayName,
|
|
'userRole': roleName,
|
|
'userInitial': displayName.charAt(0),
|
|
};
|
|
|
|
for (const id in elements) {
|
|
const el = doc.getElementById(id);
|
|
if (el) el.textContent = elements[id];
|
|
}
|
|
|
|
// 메인 대시보드 URL 설정
|
|
const dashboardBtn = doc.getElementById('dashboardBtn');
|
|
if (dashboardBtn) {
|
|
dashboardBtn.href = '/pages/dashboard.html';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 네비게이션 바와 관련된 모든 이벤트를 설정합니다.
|
|
*/
|
|
function setupNavbarEvents() {
|
|
const logoutButton = document.getElementById('logoutBtn');
|
|
if (logoutButton) {
|
|
logoutButton.addEventListener('click', () => {
|
|
if (confirm('로그아웃 하시겠습니까?')) {
|
|
clearAuthData();
|
|
window.location.href = config.paths.loginPage;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 현재 시간을 업데이트하는 함수
|
|
*/
|
|
function updateTime() {
|
|
const timeElement = document.getElementById('timeValue');
|
|
if (timeElement) {
|
|
const now = new Date();
|
|
timeElement.textContent = now.toLocaleTimeString('ko-KR', { hour12: false });
|
|
}
|
|
}
|
|
|
|
// 메인 로직: DOMContentLoaded 시 실행
|
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
if (getUser()) {
|
|
// 1. 컴포넌트 로드 및 DOM 수정
|
|
await loadComponent('navbar', '#navbar-container', processNavbarDom);
|
|
|
|
// 2. DOM에 삽입된 후에 이벤트 리스너 설정
|
|
setupNavbarEvents();
|
|
|
|
// 3. 실시간 시간 업데이트 시작
|
|
updateTime();
|
|
setInterval(updateTime, 1000);
|
|
}
|
|
}); |