refactor: 프론트엔드 SSO 인증 통합 및 API 경로 정리

- Gateway 로그인/포탈 페이지 SSO 연동
- System1 web/fastapi-bridge API base URL 동적 설정
- SSO 토큰 기반 인증 흐름 통일
- deprecated JS 파일 삭제

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-06 23:18:09 +09:00
parent ec755ed52f
commit 61c810bd47
63 changed files with 255 additions and 1357 deletions

View File

@@ -5,7 +5,6 @@ function getApiBaseUrl() {
const protocol = window.location.protocol;
const port = window.location.port;
console.log('🌐 감지된 환경:', { hostname, protocol, port });
// 🔗 nginx 프록시를 통한 접근 (권장)
// nginx가 /api/ 요청을 백엔드로 프록시하므로 포트 없이 접근
@@ -18,12 +17,11 @@ function getApiBaseUrl() {
? `${protocol}//${hostname}:${port}/api`
: `${protocol}//${hostname}/api`;
console.log('✅ nginx 프록시 사용:', baseUrl);
return baseUrl;
}
// 🚨 백업: 직접 접근 (nginx 프록시 실패시에만)
console.warn('⚠️ 직접 API 접근 (백업 모드)');
console.warn(' 직접 API 접근 (백업 모드)');
return `${protocol}//${hostname}:8000/api`;
}
@@ -64,12 +62,11 @@ export async function apiCall(url, options = {}) {
};
try {
console.log(`📡 API 호출: ${url}`);
const response = await fetch(url, finalOptions);
// 인증 만료 처리
if (response.status === 401) {
console.error(' 인증 만료');
console.error(' 인증 만료');
localStorage.removeItem('sso_token');
alert('인증이 만료되었습니다. 다시 로그인해주세요.');
window.location.href = '/';
@@ -89,11 +86,10 @@ export async function apiCall(url, options = {}) {
}
const result = await response.json();
console.log(`✅ API 성공: ${url}`);
return result;
} catch (error) {
console.error(` API 오류 (${url}):`, error);
console.error(` API 오류 (${url}):`, error);
// 네트워크 오류 vs 서버 오류 구분
if (error.name === 'TypeError' && error.message.includes('fetch')) {
@@ -105,8 +101,6 @@ export async function apiCall(url, options = {}) {
}
// 디버깅 정보
console.log('🔗 API Base URL:', API);
console.log('🌐 Current Location:', {
hostname: window.location.hostname,
protocol: window.location.protocol,
port: window.location.port,
@@ -116,21 +110,17 @@ console.log('🌐 Current Location:', {
// 🧪 API 연결 테스트 함수 (개발용)
export async function testApiConnection() {
try {
console.log('🧪 API 연결 테스트 시작...');
const response = await fetch(`${API}/health`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
});
if (response.ok) {
console.log('✅ API 연결 성공!');
return true;
} else {
console.log('❌ API 연결 실패:', response.status);
return false;
}
} catch (error) {
console.log('❌ API 연결 오류:', error.message);
return false;
}
}

View File

@@ -50,7 +50,6 @@ function getCacheStatus() {
*/
function clearCache() {
dateStatusCache.clear();
console.log('📦 캐시가 클리어되었습니다.');
}
/**
@@ -77,7 +76,6 @@ function updatePerformanceUI() {
*/
function logPerformanceStatus() {
const status = getCacheStatus();
console.log('📊 성능 상태:', status);
updatePerformanceUI();
}
@@ -118,7 +116,7 @@ function getCurrentUser() {
}
try {
const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo');
const userInfo = localStorage.getItem('sso_user');
if (userInfo) {
return JSON.parse(userInfo);
}
@@ -391,18 +389,14 @@ async function calculateDateStatus(dateStr) {
}
try {
console.log(`📊 ${dateStr} 상태 계산 시작 - 순차 호출`);
// 1단계: WorkReports 먼저 가져오기
console.log(`📝 1단계: WorkReports 조회 중...`);
const workReports = await fetchWorkReports(dateStr);
// 2초 대기 (서버 부하 방지)
console.log(`⏳ 2초 대기 중... (서버 부하 방지)`);
await new Promise(resolve => setTimeout(resolve, 2000));
// 2단계: DailyWorkReports 가져오기
console.log(`📊 2단계: DailyWorkReports 조회 중...`);
const dailyReports = await fetchDailyWorkReports(dateStr);
let status;
@@ -423,7 +417,6 @@ async function calculateDateStatus(dateStr) {
// 캐시에 저장
dateStatusCache.set(dateStr, status);
console.log(`${dateStr} 상태 계산 완료: ${status}`);
return status;
} catch (error) {
console.error('날짜 상태 계산 오류:', error);
@@ -564,10 +557,9 @@ async function loadAndUpdateDateStatus(dateStr, buttonElement) {
}`;
}
console.log(`${dateStr} 상태 로드 완료: ${status}`);
} catch (error) {
console.error(` ${dateStr} 상태 로드 실패:`, error);
console.error(` ${dateStr} 상태 로드 실패:`, error);
buttonElement.classList.remove('loading-state');
buttonElement.classList.add('error-state');
buttonElement.title = `${dateStr} - 로드 실패: ${error.message}`;
@@ -589,18 +581,14 @@ async function loadAndUpdateDateStatus(dateStr, buttonElement) {
*/
async function getWorkersForDate(dateStr) {
try {
console.log(`👥 ${dateStr} 작업자 데이터 조합 시작 - 순차 호출`);
// 1단계: WorkReports 먼저 가져오기
console.log(`📝 1단계: WorkReports 조회 중...`);
const workReports = await fetchWorkReports(dateStr);
// 2초 대기 (서버 부하 방지)
console.log(`⏳ 2초 대기 중... (서버 부하 방지)`);
await new Promise(resolve => setTimeout(resolve, 2000));
// 2단계: DailyWorkReports 가져오기
console.log(`📊 2단계: DailyWorkReports 조회 중...`);
const dailyReports = await fetchDailyWorkReports(dateStr);
const workerMap = new Map();
@@ -645,7 +633,6 @@ async function getWorkersForDate(dateStr) {
validationStatus: getValidationStatus(worker)
}));
console.log(`${dateStr} 작업자 데이터 조합 완료: ${result.length}`);
return result;
} catch (error) {
@@ -1022,11 +1009,6 @@ async function init() {
window.saveEditedWork = saveEditedWork;
window.deleteWorker = deleteWorker;
console.log('✅ 근태 검증 관리 시스템 초기화 완료 (API 통합)');
console.log(`🔗 API 경로: ${API}`);
console.log(`📊 설정: 동시 최대 ${RATE_LIMIT.maxConcurrent}개 요청, ${RATE_LIMIT.delayBetweenRequests}ms 딜레이`);
console.log('🔄 API 호출 방식: 통합 설정 + 순차 호출');
console.log('🚫 429 에러 방지: 각 날짜당 최소 5초 간격');
} catch (error) {
console.error('초기화 오류:', error);

View File

@@ -4,7 +4,6 @@ import { isLoggedIn, getUser, clearAuthData } from './auth.js';
// 즉시 실행 함수로 스코프를 보호하고 로직을 실행
(function() {
if (!isLoggedIn()) {
console.log('🚨 인증되지 않은 사용자. 로그인 페이지로 이동합니다.');
clearAuthData(); // 만약을 위해 한번 더 정리
window.location.href = '/login';
return; // 이후 코드 실행 방지
@@ -14,13 +13,12 @@ import { isLoggedIn, getUser, clearAuthData } from './auth.js';
// 사용자 정보가 유효한지 확인 (토큰은 있지만 유저 정보가 깨졌을 경우)
if (!currentUser || !currentUser.username || !currentUser.role) {
console.error('🚨 사용자 정보가 유효하지 않습니다. 강제 로그아웃 처리합니다.');
console.error(' 사용자 정보가 유효하지 않습니다. 강제 로그아웃 처리합니다.');
clearAuthData();
window.location.href = '/login';
return;
}
console.log(`${currentUser.username}(${currentUser.role})님 인증 성공.`);
// 역할 기반 메뉴 제어 로직은 각 컴포넌트 로더(load-navbar.js 등)로 이전함.
// 전역 변수 할당(window.currentUser) 제거.

View File

@@ -206,6 +206,4 @@ form?.addEventListener('submit', async (e) => {
// 페이지 로드 시 현재 사용자 정보 표시
document.addEventListener('DOMContentLoaded', () => {
const user = JSON.parse(localStorage.getItem('sso_user') || '{}');
console.log('🔐 비밀번호 변경 페이지 로드됨');
console.log('👤 현재 사용자:', user.username || 'Unknown');
});

View File

@@ -42,7 +42,7 @@ function getCurrentUser() {
}
try {
const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser');
const userInfo = localStorage.getItem('sso_user');
if (userInfo) {
const parsed = JSON.parse(userInfo);
console.log('localStorage에서 가져온 사용자 정보:', parsed);
@@ -94,7 +94,6 @@ async function loadData() {
try {
showMessage('데이터를 불러오는 중...', 'loading');
console.log('🔗 통합 API 설정을 사용한 기본 데이터 로딩 시작...');
await loadWorkers();
await loadProjects();
await loadWorkTypes();
@@ -119,7 +118,6 @@ async function loadWorkers() {
console.log('Workers API 호출 중... (통합 API 사용)');
const data = await apiCall(`${API}/workers`);
workers = Array.isArray(data) ? data : (data.workers || []);
console.log('✅ Workers 로드 성공:', workers.length);
} catch (error) {
console.error('작업자 로딩 오류:', error);
throw error;
@@ -131,7 +129,6 @@ async function loadProjects() {
console.log('Projects API 호출 중... (통합 API 사용)');
const data = await apiCall(`${API}/projects`);
projects = Array.isArray(data) ? data : (data.projects || []);
console.log('✅ Projects 로드 성공:', projects.length);
} catch (error) {
console.error('프로젝트 로딩 오류:', error);
throw error;
@@ -143,12 +140,10 @@ async function loadWorkTypes() {
const data = await apiCall(`${API}/daily-work-reports/work-types`);
if (Array.isArray(data) && data.length > 0) {
workTypes = data;
console.log('✅ 작업 유형 API 사용 (통합 설정)');
return;
}
throw new Error('API 실패');
} catch (error) {
console.log('⚠️ 작업 유형 API 사용 불가, 기본값 사용');
workTypes = [
{id: 1, name: 'Base'},
{id: 2, name: 'Vessel'},
@@ -162,12 +157,10 @@ async function loadWorkStatusTypes() {
const data = await apiCall(`${API}/daily-work-reports/work-status-types`);
if (Array.isArray(data) && data.length > 0) {
workStatusTypes = data;
console.log('✅ 업무 상태 유형 API 사용 (통합 설정)');
return;
}
throw new Error('API 실패');
} catch (error) {
console.log('⚠️ 업무 상태 유형 API 사용 불가, 기본값 사용');
workStatusTypes = [
{id: 1, name: '정규'},
{id: 2, name: '에러'}
@@ -180,12 +173,10 @@ async function loadErrorTypes() {
const data = await apiCall(`${API}/daily-work-reports/error-types`);
if (Array.isArray(data) && data.length > 0) {
errorTypes = data;
console.log('✅ 에러 유형 API 사용 (통합 설정)');
return;
}
throw new Error('API 실패');
} catch (error) {
console.log('⚠️ 에러 유형 API 사용 불가, 기본값 사용');
errorTypes = [
{id: 1, name: '설계미스'},
{id: 2, name: '외주작업 불량'},
@@ -429,10 +420,9 @@ async function saveWorkReport() {
body: JSON.stringify(requestData)
});
console.log('✅ 저장 성공 (통합 API):', result);
totalSaved++;
} catch (error) {
console.error(' 저장 실패:', error);
console.error(' 저장 실패:', error);
totalFailed++;
const workerName = workers.find(w => w.worker_id == workerId)?.worker_name || '알 수 없음';
@@ -508,10 +498,8 @@ async function loadTodayWorkers() {
queryParams += `&created_by=${currentUser.id}`;
}
console.log(`🔒 본인 입력분만 조회 (통합 API): ${API}/daily-work-reports?${queryParams}`);
const rawData = await apiCall(`${API}/daily-work-reports?${queryParams}`);
console.log('📊 당일 작업 데이터 (통합 API):', rawData);
let data = [];
if (Array.isArray(rawData)) {
@@ -789,14 +777,13 @@ async function saveEditedWork() {
body: JSON.stringify(updateData)
});
console.log('✅ 수정 성공 (통합 API):', result);
showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success');
closeEditModal();
refreshTodayWorkers();
} catch (error) {
console.error(' 수정 실패:', error);
console.error(' 수정 실패:', error);
showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error');
}
}
@@ -817,14 +804,13 @@ async function deleteWorkItem(workId) {
method: 'DELETE'
});
console.log('✅ 삭제 성공 (통합 API):', result);
showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success');
// 화면 새로고침
refreshTodayWorkers();
} catch (error) {
console.error(' 삭제 실패:', error);
console.error(' 삭제 실패:', error);
showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error');
}
}
@@ -877,7 +863,6 @@ async function init() {
setupEventListeners();
loadTodayWorkers();
console.log('✅ 시스템 초기화 완료 (통합 API 설정 적용)');
} catch (error) {
console.error('초기화 오류:', error);

View File

@@ -1,11 +1,9 @@
// /js/group-leader-dashboard.js
// 그룹장 전용 대시보드 기능
console.log('📊 그룹장 대시보드 스크립트 로딩');
// 팀 현황 새로고침
async function refreshTeamStatus() {
console.log('🔄 팀 현황 새로고침 시작');
try {
// 로딩 상태 표시
@@ -24,7 +22,7 @@ async function refreshTeamStatus() {
}, 1000);
} catch (error) {
console.error(' 팀 현황 로딩 실패:', error);
console.error(' 팀 현황 로딩 실패:', error);
const teamList = document.getElementById('team-list');
if (teamList) {
teamList.innerHTML = '<div style="text-align: center; padding: 20px; color: #f44336;">❌ 로딩 실패</div>';
@@ -64,7 +62,6 @@ function updateTeamStatusUI() {
if (presentEl) presentEl.textContent = presentCount;
if (absentEl) absentEl.textContent = absentCount;
console.log('✅ 팀 현황 업데이트 완료');
}
// 환영 메시지 개인화
@@ -74,21 +71,18 @@ function personalizeWelcome() {
if (user && user.name && welcomeMsg) {
welcomeMsg.textContent = `${user.name}님의 실시간 팀 현황 및 작업 모니터링`;
console.log('✅ 환영 메시지 개인화 완료');
}
}
// 페이지 초기화
document.addEventListener('DOMContentLoaded', function() {
console.log('🚀 그룹장 대시보드 초기화 시작');
// 사용자 정보 확인
const user = JSON.parse(localStorage.getItem('sso_user') || '{}');
console.log('👤 현재 사용자:', user);
// 권한 확인
if (user.access_level !== 'group_leader') {
console.warn('⚠️ 그룹장 권한 없음:', user.access_level);
console.warn(' 그룹장 권한 없음:', user.access_level);
// 필요시 다른 페이지로 리다이렉트
}
@@ -96,7 +90,6 @@ document.addEventListener('DOMContentLoaded', function() {
personalizeWelcome();
updateTeamStatusUI();
console.log('✅ 그룹장 대시보드 초기화 완료');
});
// 전역 함수로 내보내기 (HTML에서 사용)

View File

@@ -135,10 +135,9 @@ document.addEventListener('DOMContentLoaded', async () => {
updateTime();
setInterval(updateTime, 1000);
console.log('✅ 네비게이션 바 로딩 완료');
} catch (error) {
console.error('🔴 네비게이션 바 로딩 중 오류 발생:', error);
console.error(' 네비게이션 바 로딩 중 오류 발생:', error);
navbarContainer.innerHTML = '<p>네비게이션 바를 불러오는 데 실패했습니다.</p>';
}
});

View File

@@ -92,7 +92,6 @@ async function initializeSections() {
// 5. 모든 수정이 완료된 HTML을 실제 DOM에 한 번에 삽입
mainContainer.innerHTML = doc.body.innerHTML;
console.log(`${currentUser.role} 역할의 섹션 로딩 완료.`);
} catch (error) {
console.error('섹션 로딩 중 오류 발생:', error);

View File

@@ -58,10 +58,9 @@ document.addEventListener('DOMContentLoaded', async () => {
// 3. 수정 완료된 HTML을 실제 DOM에 삽입
sidebarContainer.innerHTML = doc.body.innerHTML;
console.log('✅ 사이드바 로딩 및 필터링 완료');
} catch (error) {
console.error('🔴 사이드바 로딩 실패:', error);
console.error(' 사이드바 로딩 실패:', error);
sidebarContainer.innerHTML = '<p>메뉴 로딩 실패</p>';
}
});

View File

@@ -47,7 +47,7 @@ function getCurrentUser() {
}
try {
const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser');
const userInfo = localStorage.getItem('sso_user');
if (userInfo) {
const parsed = JSON.parse(userInfo);
console.log('localStorage에서 가져온 사용자 정보:', parsed);
@@ -128,7 +128,6 @@ async function loadWorkers() {
console.log('작업자 데이터 로딩 중... (통합 API)');
const data = await apiCall(`${API}/workers`);
workers = Array.isArray(data) ? data : (data.workers || []);
console.log('✅ 작업자 로드 성공:', workers.length);
} catch (error) {
console.error('작업자 로딩 오류:', error);
throw error;
@@ -142,32 +141,27 @@ async function loadWorkData(date) {
// 1차: view_all=true로 전체 데이터 시도
let queryParams = `date=${date}&view_all=true`;
console.log(`🔍 1차 시도: ${API}/daily-work-reports?${queryParams}`);
let data = await apiCall(`${API}/daily-work-reports?${queryParams}`);
workData = Array.isArray(data) ? data : (data.data || []);
// 데이터가 없으면 다른 방법들 시도
if (workData.length === 0) {
console.log('⚠️ view_all로 데이터 없음, 다른 방법 시도...');
// 2차: admin=true로 시도
queryParams = `date=${date}&admin=true`;
console.log(`🔍 2차 시도: ${API}/daily-work-reports?${queryParams}`);
data = await apiCall(`${API}/daily-work-reports?${queryParams}`);
workData = Array.isArray(data) ? data : (data.data || []);
if (workData.length === 0) {
// 3차: 날짜 경로 파라미터로 시도
console.log(`🔍 3차 시도: ${API}/daily-work-reports/date/${date}`);
data = await apiCall(`${API}/daily-work-reports/date/${date}`);
workData = Array.isArray(data) ? data : (data.data || []);
if (workData.length === 0) {
// 4차: 기본 파라미터만으로 시도
console.log(`🔍 4차 시도: ${API}/daily-work-reports?date=${date}`);
data = await apiCall(`${API}/daily-work-reports?date=${date}`);
workData = Array.isArray(data) ? data : (data.data || []);
@@ -175,15 +169,11 @@ async function loadWorkData(date) {
}
}
console.log(`✅ 최종 작업 데이터 로드 결과: ${workData.length}`);
// 디버깅을 위한 상세 로그
if (workData.length > 0) {
console.log('📊 로드된 데이터 샘플:', workData.slice(0, 3));
const uniqueWorkers = [...new Set(workData.map(w => w.worker_name))];
console.log('👥 데이터에 포함된 작업자들:', uniqueWorkers);
} else {
console.log('❌ 해당 날짜에 작업 데이터가 없거나 접근 권한이 없습니다.');
}
return workData;
@@ -195,10 +185,8 @@ async function loadWorkData(date) {
// 구체적인 에러 정보 표시
if (error.message.includes('403')) {
console.log('🔒 권한 부족으로 인한 접근 제한');
throw new Error('해당 날짜의 데이터에 접근할 권한이 없습니다.');
} else if (error.message.includes('404')) {
console.log('📭 해당 날짜에 데이터 없음');
throw new Error('해당 날짜에 입력된 작업 데이터가 없습니다.');
} else {
throw error;
@@ -339,7 +327,6 @@ function displayDashboard(data) {
filteredWorkData = data.workers;
setupFiltering();
console.log('✅ 대시보드 표시 완료');
}
// 요약 섹션 표시
@@ -767,7 +754,6 @@ async function saveEditedWork(workId) {
body: JSON.stringify(updateData)
});
console.log('✅ 수정 성공 (통합 API):', result);
showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success');
closeEditModal();
@@ -777,7 +763,7 @@ async function saveEditedWork(workId) {
await loadDashboardData();
} catch (error) {
console.error(' 수정 실패:', error);
console.error(' 수정 실패:', error);
showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error');
}
}
@@ -798,7 +784,6 @@ async function deleteWorkItem(workId) {
method: 'DELETE'
});
console.log('✅ 삭제 성공 (통합 API):', result);
showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success');
closeWorkerDetailModal();
@@ -807,7 +792,7 @@ async function deleteWorkItem(workId) {
await loadDashboardData();
} catch (error) {
console.error(' 삭제 실패:', error);
console.error(' 삭제 실패:', error);
showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error');
}
}
@@ -912,7 +897,6 @@ async function init() {
// 이벤트 리스너 설정
setupEventListeners();
console.log('✅ 관리자 대시보드 초기화 완료 (통합 API 설정 적용)');
// 자동으로 오늘 데이터 로드
loadDashboardData();

View File

@@ -117,6 +117,5 @@ function showError(message) {
// 페이지 로드 시 실행
document.addEventListener('DOMContentLoaded', () => {
console.log('👤 프로필 페이지 로드됨');
loadProfile();
});

View File

@@ -71,7 +71,6 @@ class WorkReportReviewManager {
{id: 3, name: '입고지연'}, {id: 4, name: '작업 불량'}
];
} catch (error) {
console.log('⚠️ 일부 API 사용 불가, 기본값 사용');
}
// 휴가 정보 로드
@@ -101,13 +100,11 @@ class WorkReportReviewManager {
this.attendanceData = await response.json();
console.log('휴가 정보 로드 완료:', this.attendanceData.length);
} else if (response.status === 404) {
console.log('⚠️ 휴가 API 없음, 더미 데이터 생성');
this.attendanceData = this.generateDummyAttendance();
} else {
throw new Error(`휴가 정보 로드 실패: ${response.status}`);
}
} catch (error) {
console.log('⚠️ 휴가 정보 로드 오류, 더미 데이터 사용:', error.message);
this.attendanceData = this.generateDummyAttendance();
}
}
@@ -204,7 +201,6 @@ class WorkReportReviewManager {
if (response.status === 404 || response.status === 500) {
// API가 아직 준비되지 않은 경우 더미 데이터 사용
this.reports = this.generateDummyData();
console.log('⚠️ API 응답 오류, 더미 데이터 사용:', response.status);
if (response.status === 404) {
this.showMessage('⚠️ 검토 API가 준비되지 않아 더미 데이터를 표시합니다.', 'warning');
} else {
@@ -227,7 +223,6 @@ class WorkReportReviewManager {
this.updateTable();
} catch (error) {
console.log('⚠️ 네트워크 오류로 더미 데이터 사용:', error.message);
// 더미 데이터로 대체
this.reports = this.generateDummyData();
this.validateWorkHours();

View File

@@ -499,14 +499,13 @@ async function saveEditedWork(workId) {
body: JSON.stringify(updateData)
});
console.log('✅ 수정 성공 (통합 API):', result);
showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success');
closeEditModal();
refreshCurrentDay(); // 현재 날짜 데이터 새로고침
} catch (error) {
console.error(' 수정 실패:', error);
console.error(' 수정 실패:', error);
showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error');
// 버튼 복원
@@ -538,13 +537,12 @@ async function deleteWorkItem(workId) {
method: 'DELETE'
});
console.log('✅ 삭제 성공 (통합 API):', result);
showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success');
refreshCurrentDay(); // 현재 날짜 데이터 새로고침
} catch (error) {
console.error(' 삭제 실패:', error);
console.error(' 삭제 실패:', error);
showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error');
}
}
@@ -597,7 +595,7 @@ async function deleteWorkerAllWorks(date, workerName) {
refreshCurrentDay(); // 현재 날짜 데이터 새로고침
} catch (error) {
console.error(' 전체 삭제 실패:', error);
console.error(' 전체 삭제 실패:', error);
showMessage('작업 삭제 중 오류가 발생했습니다: ' + error.message, 'error');
}
}
@@ -638,7 +636,6 @@ function showConfirmDialog(title, message, warning) {
// 기본 데이터 로드 (통합 API 사용)
async function loadBasicData() {
try {
console.log('🔗 통합 API 설정을 사용한 기본 데이터 로딩...');
const promises = [
// 프로젝트 로드
@@ -695,7 +692,6 @@ async function loadBasicData() {
errorTypes
};
console.log('✅ 기본 데이터 로드 완료 (통합 API):', basicData);
} catch (error) {
console.error('기본 데이터 로드 실패:', error);
}
@@ -764,7 +760,6 @@ async function init() {
// 기본 데이터 미리 로드
await loadBasicData();
console.log('✅ 검토 페이지 초기화 완료 (통합 API 설정 적용)');
} catch (error) {
console.error('초기화 오류:', error);