feat(frontend): 공통 UI 로더 및 대시보드 구조 개선

- auth-check, load-navbar, load-sidebar 리팩토링
- auth.js 모듈을 활용하여 코드 중복 제거 및 일관성 확보
- DOMParser를 사용하여 컴포넌트 로딩 시 화면 깜빡임 현상 해결
- user-dashboard에 API 연동을 위한 견고한 기반 코드 마련
This commit is contained in:
2025-07-28 12:03:52 +09:00
parent e0e0b1ad99
commit 8d7422d376
4 changed files with 296 additions and 373 deletions

View File

@@ -1,79 +1,27 @@
// /js/auth-check.js
// 토큰 검증과 권한 체크
// /js/auth-check.js
import { isLoggedIn, getUser, clearAuthData } from './auth.js';
const token = localStorage.getItem('token');
function isValidJWT(token) {
return typeof token === 'string' && token.split('.').length === 3;
}
function getPayload(token) {
try {
return JSON.parse(atob(token.split('.')[1]));
} catch {
return null;
}
}
if (!token || !isValidJWT(token)) {
console.log('🚨 토큰이 없거나 유효하지 않음');
localStorage.removeItem('token');
localStorage.removeItem('user');
window.location.href = '/index.html';
} else {
const user = getPayload(token);
const storedUser = JSON.parse(localStorage.getItem('user') || '{}');
console.log('🔐 JWT 사용자 정보:', user);
console.log('💾 저장된 사용자 정보:', storedUser);
// 사용자 정보 우선순위: localStorage > JWT payload
const currentUser = storedUser.access_level ? storedUser : user;
if (!currentUser || !currentUser.username || !currentUser.access_level) {
console.log('🚨 사용자 정보가 유효하지 않음');
localStorage.removeItem('token');
localStorage.removeItem('user');
// 즉시 실행 함수로 스코프를 보호하고 로직을 실행
(function() {
if (!isLoggedIn()) {
console.log('🚨 인증되지 않은 사용자. 로그인 페이지로 이동합니다.');
clearAuthData(); // 만약을 위해 한번 더 정리
window.location.href = '/index.html';
} else {
console.log('✅ 인증 성공:', currentUser.username, currentUser.access_level);
// 사용자 이름 표시
const userNameElements = document.querySelectorAll('#user-name, .user-name');
userNameElements.forEach(el => {
if (el) el.textContent = currentUser.name || currentUser.username;
});
// 🎯 역할별 메뉴 표시/숨김 처리
const accessLevel = currentUser.access_level;
// 관리자 전용 메뉴
if (accessLevel !== 'admin' && accessLevel !== 'system') {
const adminOnly = document.querySelectorAll('.admin-only, .system-only');
adminOnly.forEach(el => el.remove());
}
// 그룹장 전용 메뉴
if (accessLevel !== 'group_leader') {
const groupLeaderOnly = document.querySelectorAll('.group-leader-only');
groupLeaderOnly.forEach(el => el.remove());
}
// 지원팀 전용 메뉴
if (accessLevel !== 'support') {
const supportOnly = document.querySelectorAll('.support-only');
supportOnly.forEach(el => el.remove());
}
// 일반 작업자 전용 메뉴
if (accessLevel !== 'worker' && accessLevel !== 'user') {
const workerOnly = document.querySelectorAll('.worker-only');
workerOnly.forEach(el => el.remove());
}
// 전역 사용자 정보 저장
window.currentUser = currentUser;
console.log('🎭 역할별 메뉴 필터링 완료:', accessLevel);
return; // 이후 코드 실행 방지
}
}
const currentUser = getUser();
// 사용자 정보가 유효한지 확인 (토큰은 있지만 유저 정보가 깨졌을 경우)
if (!currentUser || !currentUser.username || !currentUser.role) {
console.error('🚨 사용자 정보가 유효하지 않습니다. 강제 로그아웃 처리합니다.');
clearAuthData();
window.location.href = '/index.html';
return;
}
console.log(`${currentUser.username}(${currentUser.role})님 인증 성공.`);
// 역할 기반 메뉴 제어 로직은 각 컴포넌트 로더(load-navbar.js 등)로 이전함.
// 전역 변수 할당(window.currentUser) 제거.
})();