// 인증 관련 JavaScript 함수들 const API_BASE_URL = 'http://localhost:14001/api'; // 로그인 함수 async function login(username, password) { try { const response = await fetch(`${API_BASE_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ username, password }) }); const data = await response.json(); if (response.ok) { // 토큰과 사용자 정보 저장 localStorage.setItem('token', data.token); localStorage.setItem('user', JSON.stringify(data.user)); // 대시보드로 이동 window.location.href = 'dashboard.html'; } else { throw new Error(data.message || '로그인에 실패했습니다.'); } } catch (error) { console.error('로그인 오류:', error); showAlert('로그인 실패', error.message); } } // 로그아웃 함수 function logout() { localStorage.removeItem('token'); localStorage.removeItem('user'); window.location.href = 'index.html'; } // 토큰 확인 함수 function checkAuth() { const token = localStorage.getItem('token'); const user = localStorage.getItem('user'); if (!token || !user) { // 로그인 페이지가 아닌 경우에만 리다이렉트 if (!window.location.pathname.includes('index.html') && window.location.pathname !== '/') { window.location.href = 'index.html'; } return null; } try { return JSON.parse(user); } catch (error) { console.error('사용자 정보 파싱 오류:', error); logout(); return null; } } // 관리자 권한 확인 function isAdmin() { const user = checkAuth(); return user && user.role === 'admin'; } // API 요청 헤더에 토큰 추가 function getAuthHeaders() { const token = localStorage.getItem('token'); return { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }; } // API 요청 함수 async function apiRequest(url, options = {}) { const defaultOptions = { headers: getAuthHeaders() }; const mergedOptions = { ...defaultOptions, ...options, headers: { ...defaultOptions.headers, ...options.headers } }; try { const response = await fetch(`${API_BASE_URL}${url}`, mergedOptions); // 인증 오류 처리 if (response.status === 401) { logout(); return; } const data = await response.json(); if (!response.ok) { throw new Error(data.message || '요청 처리에 실패했습니다.'); } return data; } catch (error) { console.error('API 요청 오류:', error); throw error; } } // 알림 표시 함수 function showAlert(title, message, type = 'danger') { const alertModal = document.getElementById('alertModal'); if (alertModal) { document.getElementById('alertMessage').innerHTML = `${title}
${message}`; const modal = new bootstrap.Modal(alertModal); modal.show(); } else { alert(`${title}: ${message}`); } } // 토스트 알림 표시 함수 function showToast(message, type = 'success') { const toastElement = document.getElementById('alertToast'); const toastMessage = document.getElementById('toastMessage'); if (toastElement && toastMessage) { toastMessage.textContent = message; // 토스트 색상 설정 toastElement.className = `toast ${type === 'success' ? 'bg-success' : 'bg-danger'} text-white`; const toast = new bootstrap.Toast(toastElement); toast.show(); } } // 페이지 로드 시 인증 확인 document.addEventListener('DOMContentLoaded', function() { // 로그인 페이지가 아닌 경우 인증 확인 if (!window.location.pathname.includes('index.html') && window.location.pathname !== '/') { const user = checkAuth(); if (user) { // 사용자 이름 표시 const userNameDisplay = document.getElementById('userNameDisplay'); if (userNameDisplay) { userNameDisplay.textContent = user.name; } // 관리자가 아닌 경우 작업자 관리 메뉴 숨기기 if (!isAdmin()) { const workerManagementNav = document.getElementById('workerManagementNav'); const addWorkerBtn = document.getElementById('addWorkerBtn'); if (workerManagementNav) workerManagementNav.style.display = 'none'; if (addWorkerBtn) addWorkerBtn.style.display = 'none'; } } } // 로그인 폼 처리 const loginForm = document.getElementById('loginForm'); if (loginForm) { loginForm.addEventListener('submit', async function(e) { e.preventDefault(); const username = document.getElementById('username').value; const password = document.getElementById('password').value; if (!username || !password) { showAlert('입력 오류', '아이디와 비밀번호를 모두 입력해주세요.'); return; } await login(username, password); }); } }); // 날짜 포맷 함수 function formatDate(dateString) { const date = new Date(dateString); return date.toLocaleDateString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit' }); } // 시간 포맷 함수 function formatTime(timeString) { if (!timeString) return ''; return timeString.substring(0, 5); // HH:MM 형식으로 자르기 } // 직종 한글 변환 function getJobTypeText(jobType) { const jobTypes = { 'welder': '용접사', 'plumber': '배관사' }; return jobTypes[jobType] || jobType; } // 상태 한글 변환 function getStatusText(status, type = 'general') { const statusTexts = { general: { 'active': '활성', 'inactive': '비활성', 'pending': '대기', 'approved': '승인', 'rejected': '거부', 'completed': '완료', 'cancelled': '취소' }, work: { 'planned': '계획', 'in_progress': '진행중', 'completed': '완료', 'cancelled': '취소' }, error: { 'reported': '신고됨', 'investigating': '조사중', 'resolved': '해결됨', 'closed': '종료' }, request: { 'pending': '대기', 'approved': '승인', 'ordered': '주문', 'delivered': '배송완료', 'rejected': '거부' } }; return statusTexts[type][status] || status; } // 우선순위 한글 변환 function getPriorityText(priority) { const priorities = { 'low': '낮음', 'normal': '보통', 'high': '높음', 'urgent': '긴급' }; return priorities[priority] || priority; } // 심각도 한글 변환 function getSeverityText(severity) { const severities = { 'low': '낮음', 'medium': '보통', 'high': '높음', 'critical': '심각' }; return severities[severity] || severity; }