refactor: 전체 페이지 이모지 제거 및 사이드바 레이아웃 수정
- 모든 페이지에서 이모지 제거 (CODING_GUIDE 준수) - admin/ (9개), safety/ (7개), work/ (4개) - attendance/ (8개), profile/ (2개) - 사이드바 CSS에 누락된 컨테이너 클래스 추가 - work-report-container, analysis-container, dashboard-main - 사이드바 토글 시 메인 콘텐츠 정상 반응하도록 수정 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
<link rel="icon" type="image/png" href="/img/favicon.png">
|
||||
<script src="/js/auth-check.js?v=1" defer></script>
|
||||
<script type="module" src="/js/api-config.js?v=3"></script>
|
||||
<script type="module" src="/js/load-navbar.js"></script>
|
||||
<script type="module" src="/js/load-sidebar.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -26,20 +28,17 @@
|
||||
|
||||
<!-- 페이지 헤더 -->
|
||||
<header class="page-header fade-in">
|
||||
<h1 class="page-title">
|
||||
<span class="icon">📊</span>
|
||||
작업 분석
|
||||
</h1>
|
||||
<h1 class="page-title">작업 분석</h1>
|
||||
<p class="page-subtitle">기간별/프로젝트별 작업 현황을 분석하고 통계를 확인합니다</p>
|
||||
</header>
|
||||
|
||||
<!-- 분석 모드 탭 -->
|
||||
<nav class="analysis-tabs fade-in">
|
||||
<button class="tab-button active" data-mode="period" onclick="switchAnalysisMode('period')">
|
||||
📅 기간별 분석
|
||||
기간별 분석
|
||||
</button>
|
||||
<button class="tab-button" data-mode="project" onclick="switchAnalysisMode('project')">
|
||||
🏗️ 프로젝트별 분석
|
||||
프로젝트별 분석
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
@@ -48,33 +47,23 @@
|
||||
<div class="controls-grid">
|
||||
<!-- 기간 설정 -->
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="startDate">
|
||||
<span class="icon">📅</span>
|
||||
시작일
|
||||
</label>
|
||||
<label class="form-label" for="startDate">시작일</label>
|
||||
<input type="date" id="startDate" class="form-input" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="endDate">
|
||||
<span class="icon">📅</span>
|
||||
종료일
|
||||
</label>
|
||||
<label class="form-label" for="endDate">종료일</label>
|
||||
<input type="date" id="endDate" class="form-input" required>
|
||||
</div>
|
||||
|
||||
<!-- 기간 확정 버튼 -->
|
||||
<div class="form-group">
|
||||
<button class="confirm-period-button" onclick="confirmPeriod()">
|
||||
<span class="icon">✅</span>
|
||||
기간 확정
|
||||
</button>
|
||||
<button class="confirm-period-button" onclick="confirmPeriod()">기간 확정</button>
|
||||
</div>
|
||||
|
||||
<!-- 기간 상태 표시 -->
|
||||
<div class="form-group" id="periodStatusGroup" style="display: none;">
|
||||
<div class="period-status">
|
||||
<span class="icon">✅</span>
|
||||
<div>
|
||||
<div style="font-size: 0.8rem; opacity: 0.8; margin-bottom: 2px;">분석 기간</div>
|
||||
<div id="periodText">기간이 설정되지 않았습니다</div>
|
||||
@@ -96,19 +85,15 @@
|
||||
<div id="analysisTabNavigation" class="tab-navigation" style="display: none;">
|
||||
<div class="tab-buttons">
|
||||
<button class="tab-button active" data-tab="work-status">
|
||||
<span class="icon">📈</span>
|
||||
기간별 작업 현황
|
||||
</button>
|
||||
<button class="tab-button" data-tab="project-distribution">
|
||||
<span class="icon">🥧</span>
|
||||
프로젝트별 분포
|
||||
</button>
|
||||
<button class="tab-button" data-tab="worker-performance">
|
||||
<span class="icon">👤</span>
|
||||
작업자별 성과
|
||||
</button>
|
||||
<button class="tab-button" data-tab="error-analysis">
|
||||
<span class="icon">⚠️</span>
|
||||
오류 분석
|
||||
</button>
|
||||
</div>
|
||||
@@ -125,14 +110,8 @@
|
||||
<div id="work-status-tab" class="tab-content active">
|
||||
<div class="chart-container table-type">
|
||||
<div class="chart-header">
|
||||
<h3 class="chart-title">
|
||||
<span class="icon">📈</span>
|
||||
기간별 작업 현황
|
||||
</h3>
|
||||
<button class="chart-analyze-btn" onclick="analyzeWorkStatus()" disabled>
|
||||
<span class="icon">🔍</span>
|
||||
분석 실행
|
||||
</button>
|
||||
<h3 class="chart-title">기간별 작업 현황</h3>
|
||||
<button class="chart-analyze-btn" onclick="analyzeWorkStatus()" disabled>분석 실행</button>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<table class="work-report-table" id="workReportTable">
|
||||
@@ -172,14 +151,8 @@
|
||||
<div id="project-distribution-tab" class="tab-content">
|
||||
<div class="chart-container table-type">
|
||||
<div class="chart-header">
|
||||
<h3 class="chart-title">
|
||||
<span class="icon">📋</span>
|
||||
프로젝트별 작업 분포
|
||||
</h3>
|
||||
<button class="chart-analyze-btn" onclick="analyzeProjectDistribution()" disabled>
|
||||
<span class="icon">🔍</span>
|
||||
분석 실행
|
||||
</button>
|
||||
<h3 class="chart-title">프로젝트별 작업 분포</h3>
|
||||
<button class="chart-analyze-btn" onclick="analyzeProjectDistribution()" disabled>분석 실행</button>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<table class="production-report-table" id="projectDistributionTable">
|
||||
@@ -216,14 +189,8 @@
|
||||
<div id="worker-performance-tab" class="tab-content">
|
||||
<div class="chart-container chart-type">
|
||||
<div class="chart-header">
|
||||
<h3 class="chart-title">
|
||||
<span class="icon">👤</span>
|
||||
작업자별 성과
|
||||
</h3>
|
||||
<button class="chart-analyze-btn" onclick="analyzeWorkerPerformance()" disabled>
|
||||
<span class="icon">🔍</span>
|
||||
분석 실행
|
||||
</button>
|
||||
<h3 class="chart-title">작업자별 성과</h3>
|
||||
<button class="chart-analyze-btn" onclick="analyzeWorkerPerformance()" disabled>분석 실행</button>
|
||||
</div>
|
||||
<canvas id="workerPerformanceChart" class="chart-canvas"></canvas>
|
||||
</div>
|
||||
@@ -233,14 +200,8 @@
|
||||
<div id="error-analysis-tab" class="tab-content">
|
||||
<div class="chart-container table-type">
|
||||
<div class="chart-header">
|
||||
<h3 class="chart-title">
|
||||
<span class="icon">⚠️</span>
|
||||
오류 분석
|
||||
</h3>
|
||||
<button class="chart-analyze-btn" onclick="analyzeErrorAnalysis()" disabled>
|
||||
<span class="icon">🔍</span>
|
||||
분석 실행
|
||||
</button>
|
||||
<h3 class="chart-title">오류 분석</h3>
|
||||
<button class="chart-analyze-btn" onclick="analyzeErrorAnalysis()" disabled>분석 실행</button>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<table class="error-analysis-table" id="errorAnalysisTable">
|
||||
@@ -279,10 +240,7 @@
|
||||
<!-- 상세 데이터 테이블 -->
|
||||
<div id="dataTableContainer" class="data-table-container" style="display: none;">
|
||||
<div class="table-header">
|
||||
<h3 class="table-title">
|
||||
<span class="icon">📋</span>
|
||||
상세 작업 데이터
|
||||
</h3>
|
||||
<h3 class="table-title">상세 작업 데이터</h3>
|
||||
</div>
|
||||
<div style="overflow-x: auto;">
|
||||
<table class="data-table" id="detailDataTable">
|
||||
@@ -330,13 +288,13 @@
|
||||
if (useCache && this.cache.has(cacheKey)) {
|
||||
const cached = this.cache.get(cacheKey);
|
||||
if (Date.now() - cached.timestamp < this.CACHE_DURATION) {
|
||||
console.log('📦 캐시에서 데이터 반환:', endpoint);
|
||||
console.log('[Cache] 캐시에서 데이터 반환:', endpoint);
|
||||
return cached.data;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('🌐 API 호출:', endpoint);
|
||||
console.log('[API] 호출:', endpoint);
|
||||
const response = await window.apiCall(endpoint, method, data);
|
||||
|
||||
// 성공 시 캐시 저장
|
||||
@@ -349,34 +307,34 @@
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ API 호출 실패:', endpoint, error);
|
||||
console.error('[Error] API 호출 실패:', endpoint, error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 배치 API 호출 (병렬 처리)
|
||||
async batchCall(requests) {
|
||||
console.log('🔄 배치 API 호출 시작:', requests.length, '개');
|
||||
console.log('[Batch] API 호출 시작:', requests.length, '개');
|
||||
|
||||
const promises = requests.map(async (req) => {
|
||||
try {
|
||||
const result = await this.call(req.endpoint, req.method, req.data, req.useCache);
|
||||
return { name: req.name, success: true, data: result };
|
||||
} catch (error) {
|
||||
console.warn(`⚠️ ${req.name} API 실패:`, error);
|
||||
console.warn(`[Warning] ${req.name} API 실패:`, error);
|
||||
return { name: req.name, success: false, error: error.message, data: null };
|
||||
}
|
||||
});
|
||||
|
||||
const results = await Promise.all(promises);
|
||||
console.log('✅ 배치 API 호출 완료');
|
||||
console.log('[Complete] 배치 API 호출 완료');
|
||||
return results;
|
||||
},
|
||||
|
||||
// 캐시 초기화
|
||||
clearCache() {
|
||||
this.cache.clear();
|
||||
console.log('🗑️ API 캐시 초기화');
|
||||
console.log('[Clear] API 캐시 초기화');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -453,7 +411,7 @@
|
||||
toast.className = `error-toast toast-${type}`;
|
||||
toast.innerHTML = `
|
||||
<div class="toast-content">
|
||||
<span class="toast-icon">${type === 'error' ? '⚠️' : type === 'success' ? '✅' : 'ℹ️'}</span>
|
||||
<span class="toast-icon">${type === 'error' ? '[!]' : type === 'success' ? '[v]' : '[i]'}</span>
|
||||
<span class="toast-message">${message}</span>
|
||||
<button class="toast-close" onclick="this.parentElement.parentElement.remove()">×</button>
|
||||
</div>
|
||||
@@ -491,7 +449,7 @@
|
||||
const userMessage = this.UserMessages[errorType];
|
||||
|
||||
// 콘솔에 상세 로그
|
||||
console.error(`❌ [${context}] ${errorType.toUpperCase()} 오류:`, error);
|
||||
console.error(`[Error] [${context}] ${errorType.toUpperCase()} 오류:`, error);
|
||||
|
||||
// 사용자에게 친화적 메시지 표시
|
||||
if (showUserMessage) {
|
||||
|
||||
Reference in New Issue
Block a user