fix: 그룹 리더 대시보드 작업 저장/삭제 오류 해결 및 작업 분석 시스템 성능 최적화

🔧 그룹 리더 대시보드 수정사항:
- API 호출 방식 수정 (modern-dashboard.js)
- 서버 API 요구사항에 맞는 데이터 구조 변경
- work_entries 배열 구조로 변경
- work_type_id → task_id 필드명 매핑
- 400 Bad Request 오류 해결

 작업 분석 시스템 성능 최적화:
- 중복 함수 제거 (isWeekend, isVacationProject 통합)
- WorkAnalysisAPI 캐싱 시스템 구현 (5분 만료)
- 네임스페이스 조직화 (utils, ui, analysis, render)
- ErrorHandler 통합 에러 처리 시스템
- 성능 모니터링 및 메모리 누수 방지
- GPU 가속 CSS 애니메이션 추가
- 디바운스/스로틀 함수 적용
- 의미 없는 통계 카드 제거

📊 작업 분석 페이지 개선:
- 프로그레스 바 애니메이션
- 토스트 알림 시스템
- 부드러운 전환 효과
- 반응형 최적화
- 메모리 사용량 모니터링
This commit is contained in:
Hyungi Ahn
2025-11-05 10:12:52 +09:00
parent 052e868599
commit ed40eec261
14 changed files with 8740 additions and 243 deletions

View File

@@ -752,10 +752,7 @@ async function processVacation(workerId, vacationType, hours) {
created_by: currentUser?.user_id || 1
};
const response = await window.apiCall(`${window.API}/daily-work-reports`, {
method: 'POST',
body: JSON.stringify(vacationReport)
});
const response = await window.apiCall('/daily-work-reports', 'POST', vacationReport);
showToast(`휴가 처리가 완료되었습니다.`, 'success');
await loadDashboardData(); // 데이터 새로고침
@@ -998,7 +995,7 @@ async function loadModalData() {
async function loadModalExistingWork() {
try {
const response = await window.apiCall(`${window.API}/daily-work-reports?date=${currentModalWorker.date}&worker_id=${currentModalWorker.id}`);
const response = await window.apiCall(`/daily-work-reports?date=${currentModalWorker.date}&worker_id=${currentModalWorker.id}`);
modalExistingWork = Array.isArray(response) ? response : (response.data || []);
} catch (error) {
console.error('기존 작업 로드 오류:', error);
@@ -1009,10 +1006,10 @@ async function loadModalExistingWork() {
async function loadModalDropdownData() {
try {
const [projectsRes, workTypesRes, workStatusRes, errorTypesRes] = await Promise.all([
window.apiCall(`${window.API}/projects/active/list`),
window.apiCall(`${window.API}/daily-work-reports/work-types`),
window.apiCall(`${window.API}/daily-work-reports/work-status-types`),
window.apiCall(`${window.API}/daily-work-reports/error-types`)
window.apiCall('/projects/active/list'),
window.apiCall('/daily-work-reports/work-types'),
window.apiCall('/daily-work-reports/work-status-types'),
window.apiCall('/daily-work-reports/error-types')
]);
modalProjects = Array.isArray(projectsRes) ? projectsRes : (projectsRes.data || []);
@@ -1153,18 +1150,20 @@ async function saveModalNewWork() {
const workData = {
report_date: currentModalWorker.date,
worker_id: currentModalWorker.id,
project_id: parseInt(projectId),
work_type_id: parseInt(workTypeId),
work_status_id: parseInt(workStatusId),
error_type_id: workStatusId === '2' ? parseInt(errorTypeId) : null,
work_hours: parseFloat(workHours),
created_by: currentUser?.user_id || 1
work_entries: [{
project_id: parseInt(projectId),
task_id: parseInt(workTypeId), // work_type_id를 task_id로 매핑
work_hours: parseFloat(workHours),
work_status_id: parseInt(workStatusId),
error_type_id: workStatusId === '2' ? parseInt(errorTypeId) : null,
description: '' // 기본 설명
}]
};
await window.apiCall(`${window.API}/daily-work-reports`, {
method: 'POST',
body: JSON.stringify(workData)
});
console.log('📤 전송할 작업 데이터:', workData);
console.log('📋 현재 사용자:', currentUser);
await window.apiCall('/daily-work-reports', 'POST', workData);
showToast('작업이 성공적으로 저장되었습니다.', 'success');
@@ -1189,9 +1188,7 @@ async function deleteModalWork(workId) {
}
try {
await window.apiCall(`${window.API}/daily-work-reports/${workId}`, {
method: 'DELETE'
});
await window.apiCall(`/daily-work-reports/${workId}`, 'DELETE');
showToast('작업이 성공적으로 삭제되었습니다.', 'success');