- api-base.js에 4개 전역 유틸리티 추가 (showToast, formatDate, waitForApi, generateUUID) - 24개 파일에서 중복 정의 제거 (-932줄) - showToast: 18곳 중복 → 1곳 통합 (자동 컨테이너/스타일 생성) - waitForApi/waitForApiConfig/waitForApiCall: 5곳 → 1곳 통합 - generateUUID: tbm.js 중복 제거 - tbm/utils.js, workplace-management/utils.js: window 재정의 제거 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
179 lines
5.0 KiB
JavaScript
179 lines
5.0 KiB
JavaScript
// 작업 관리 페이지 JavaScript
|
|
|
|
// 전역 변수
|
|
let statsData = {
|
|
projects: 0,
|
|
workers: 0,
|
|
tasks: 0,
|
|
codeTypes: 0
|
|
};
|
|
|
|
// 페이지 초기화
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
console.log('🔧 작업 관리 페이지 초기화 시작');
|
|
|
|
initializePage();
|
|
loadStatistics();
|
|
});
|
|
|
|
// 페이지 초기화
|
|
function initializePage() {
|
|
// 시간 업데이트 시작
|
|
updateCurrentTime();
|
|
setInterval(updateCurrentTime, 1000);
|
|
|
|
// 사용자 정보 업데이트
|
|
updateUserInfo();
|
|
|
|
// 프로필 메뉴 토글
|
|
setupProfileMenu();
|
|
|
|
// 로그아웃 버튼
|
|
setupLogoutButton();
|
|
}
|
|
|
|
// 현재 시간 업데이트 (시 분 초 형식으로 고정)
|
|
function updateCurrentTime() {
|
|
const now = new Date();
|
|
const hours = String(now.getHours()).padStart(2, '0');
|
|
const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
const seconds = String(now.getSeconds()).padStart(2, '0');
|
|
const timeString = `${hours}시 ${minutes}분 ${seconds}초`;
|
|
|
|
const timeElement = document.getElementById('timeValue');
|
|
if (timeElement) {
|
|
timeElement.textContent = timeString;
|
|
}
|
|
}
|
|
|
|
// navbar/sidebar는 app-init.js에서 공통 처리
|
|
function updateUserInfo() {
|
|
// app-init.js가 navbar 사용자 정보를 처리
|
|
}
|
|
|
|
// 프로필 메뉴 설정
|
|
function setupProfileMenu() {
|
|
const userProfile = document.getElementById('userProfile');
|
|
const profileMenu = document.getElementById('profileMenu');
|
|
|
|
if (userProfile && profileMenu) {
|
|
userProfile.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
const isVisible = profileMenu.style.display === 'block';
|
|
profileMenu.style.display = isVisible ? 'none' : 'block';
|
|
});
|
|
|
|
// 외부 클릭 시 메뉴 닫기
|
|
document.addEventListener('click', function() {
|
|
profileMenu.style.display = 'none';
|
|
});
|
|
}
|
|
}
|
|
|
|
// 로그아웃 버튼 설정
|
|
function setupLogoutButton() {
|
|
const logoutBtn = document.getElementById('logoutBtn');
|
|
if (logoutBtn) {
|
|
logoutBtn.addEventListener('click', function() {
|
|
if (confirm('로그아웃 하시겠습니까?')) {
|
|
localStorage.removeItem('sso_token');
|
|
localStorage.removeItem('sso_user');
|
|
localStorage.removeItem('userInfo');
|
|
window.location.href = '/login';
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// 통계 데이터 로드
|
|
async function loadStatistics() {
|
|
try {
|
|
console.log('📊 통계 데이터 로딩 시작');
|
|
|
|
// 프로젝트 수 조회
|
|
try {
|
|
const projectsResponse = await apiCall('/projects', 'GET');
|
|
if (projectsResponse && Array.isArray(projectsResponse)) {
|
|
statsData.projects = projectsResponse.length;
|
|
updateStatDisplay('projectCount', statsData.projects);
|
|
}
|
|
} catch (error) {
|
|
console.warn('프로젝트 통계 로드 실패:', error);
|
|
updateStatDisplay('projectCount', '오류');
|
|
}
|
|
|
|
// 작업자 수 조회
|
|
try {
|
|
const workersResponse = await apiCall('/workers', 'GET');
|
|
if (workersResponse && Array.isArray(workersResponse)) {
|
|
const activeWorkers = workersResponse.filter(w => w.status === 'active');
|
|
statsData.workers = activeWorkers.length;
|
|
updateStatDisplay('workerCount', statsData.workers);
|
|
}
|
|
} catch (error) {
|
|
console.warn('작업자 통계 로드 실패:', error);
|
|
updateStatDisplay('workerCount', '오류');
|
|
}
|
|
|
|
// 작업 유형 수 조회
|
|
try {
|
|
const tasksResponse = await apiCall('/tasks', 'GET');
|
|
if (tasksResponse && Array.isArray(tasksResponse)) {
|
|
const activeTasks = tasksResponse.filter(t => t.is_active);
|
|
statsData.tasks = activeTasks.length;
|
|
updateStatDisplay('taskCount', statsData.tasks);
|
|
}
|
|
} catch (error) {
|
|
console.warn('작업 유형 통계 로드 실패:', error);
|
|
updateStatDisplay('taskCount', '오류');
|
|
}
|
|
|
|
// 코드 타입 수 조회 (임시로 고정값)
|
|
statsData.codeTypes = 3; // ISSUE_TYPE, ERROR_TYPE, WORK_STATUS
|
|
updateStatDisplay('codeTypeCount', statsData.codeTypes);
|
|
|
|
console.log('✅ 통계 데이터 로딩 완료:', statsData);
|
|
|
|
} catch (error) {
|
|
console.error('통계 데이터 로딩 오류:', error);
|
|
}
|
|
}
|
|
|
|
// 통계 표시 업데이트
|
|
function updateStatDisplay(elementId, value) {
|
|
const element = document.getElementById(elementId);
|
|
if (element) {
|
|
element.textContent = value;
|
|
|
|
// 애니메이션 효과
|
|
element.style.transform = 'scale(1.1)';
|
|
setTimeout(() => {
|
|
element.style.transform = 'scale(1)';
|
|
}, 200);
|
|
}
|
|
}
|
|
|
|
// 최근 활동 관련 함수들 제거됨
|
|
|
|
// 페이지 네비게이션
|
|
function navigateToPage(url) {
|
|
console.log(`🔗 페이지 이동: ${url}`);
|
|
|
|
// 로딩 효과
|
|
const card = event.currentTarget;
|
|
const originalContent = card.innerHTML;
|
|
|
|
card.style.opacity = '0.7';
|
|
card.style.pointerEvents = 'none';
|
|
|
|
// 잠시 후 페이지 이동
|
|
setTimeout(() => {
|
|
window.location.href = url;
|
|
}, 300);
|
|
}
|
|
|
|
// showToast → api-base.js 전역 사용
|
|
|
|
// 전역 함수로 노출
|
|
window.navigateToPage = navigateToPage;
|