// 안전관리 대시보드 JavaScript let currentStatus = 'pending'; let requests = []; let currentRejectRequestId = null; // showToast → api-base.js 전역 사용 // ==================== 초기화 ==================== document.addEventListener('DOMContentLoaded', async () => { await loadRequests(); updateStats(); }); // ==================== 데이터 로드 ==================== /** * 출입 신청 목록 로드 */ async function loadRequests() { try { const filters = currentStatus === 'all' ? {} : { status: currentStatus }; const queryString = new URLSearchParams(filters).toString(); const response = await window.apiCall(`/workplace-visits/requests?${queryString}`, 'GET'); if (response && response.success) { requests = response.data || []; renderRequestTable(); updateStats(); } } catch (error) { console.error('출입 신청 목록 로드 오류:', error); showToast('출입 신청 목록을 불러오는데 실패했습니다.', 'error'); } } /** * 통계 업데이트 */ async function updateStats() { try { const response = await window.apiCall('/workplace-visits/requests', 'GET'); if (response && response.success) { const allRequests = response.data || []; const stats = { pending: allRequests.filter(r => r.status === 'pending').length, approved: allRequests.filter(r => r.status === 'approved').length, training_completed: allRequests.filter(r => r.status === 'training_completed').length, rejected: allRequests.filter(r => r.status === 'rejected').length }; document.getElementById('statPending').textContent = stats.pending; document.getElementById('statApproved').textContent = stats.approved; document.getElementById('statTrainingCompleted').textContent = stats.training_completed; document.getElementById('statRejected').textContent = stats.rejected; } } catch (error) { console.error('통계 업데이트 오류:', error); } } /** * 테이블 렌더링 */ function renderRequestTable() { const container = document.getElementById('requestTableContainer'); if (requests.length === 0) { container.innerHTML = `
📭

출입 신청이 없습니다

현재 ${getStatusText(currentStatus)} 상태의 신청이 없습니다.

`; return; } let html = ` `; requests.forEach(req => { const statusText = { 'pending': '승인 대기', 'approved': '승인됨', 'rejected': '반려됨', 'training_completed': '교육 완료' }[req.status] || req.status; html += ` `; }); html += `
신청일 신청자 방문자 인원 방문 작업장 방문 일시 목적 상태 작업
${new Date(req.created_at).toLocaleDateString()} ${req.requester_full_name || req.requester_name} ${req.visitor_company} ${req.visitor_count}명 ${req.category_name} - ${req.workplace_name} ${req.visit_date} ${req.visit_time} ${req.purpose_name} ${statusText}
${req.status === 'pending' ? ` ` : ''} ${req.status === 'approved' ? ` ` : ''}
`; container.innerHTML = html; } /** * 상태 텍스트 변환 */ function getStatusText(status) { const map = { 'pending': '승인 대기', 'approved': '승인 완료', 'rejected': '반려', 'training_completed': '교육 완료', 'all': '전체' }; return map[status] || status; } // ==================== 탭 전환 ==================== /** * 탭 전환 */ async function switchTab(status) { currentStatus = status; // 탭 활성화 상태 변경 document.querySelectorAll('.status-tab').forEach(tab => { if (tab.dataset.status === status) { tab.classList.add('active'); } else { tab.classList.remove('active'); } }); await loadRequests(); } // ==================== 상세보기 ==================== /** * 상세보기 모달 열기 */ async function viewDetail(requestId) { try { const response = await window.apiCall(`/workplace-visits/requests/${requestId}`, 'GET'); if (response && response.success) { const req = response.data; const statusText = { 'pending': '승인 대기', 'approved': '승인됨', 'rejected': '반려됨', 'training_completed': '교육 완료' }[req.status] || req.status; let html = `
신청 번호
#${req.request_id}
신청일
${new Date(req.created_at).toLocaleString()}
신청자
${req.requester_full_name || req.requester_name}
방문자 소속
${req.visitor_company}
방문 인원
${req.visitor_count}명
방문 구역
${req.category_name}
방문 작업장
${req.workplace_name}
방문 날짜
${req.visit_date}
방문 시간
${req.visit_time}
방문 목적
${req.purpose_name}
상태
${statusText}
`; if (req.notes) { html += `
비고:
${req.notes}
`; } if (req.rejection_reason) { html += `
반려 사유:
${req.rejection_reason}
`; } if (req.approved_by) { html += `
처리 정보:
처리자: ${req.approver_name || 'Unknown'}
처리 시간: ${new Date(req.approved_at).toLocaleString()}
`; } document.getElementById('detailContent').innerHTML = html; document.getElementById('detailModal').style.display = 'flex'; } } catch (error) { console.error('상세 정보 로드 오류:', error); showToast('상세 정보를 불러오는데 실패했습니다.', 'error'); } } /** * 상세보기 모달 닫기 */ function closeDetailModal() { document.getElementById('detailModal').style.display = 'none'; } // ==================== 승인/반려 ==================== /** * 승인 처리 */ async function approveRequest(requestId) { if (!confirm('이 출입 신청을 승인하시겠습니까?')) { return; } try { const response = await window.apiCall(`/workplace-visits/requests/${requestId}/approve`, 'PUT'); if (response && response.success) { showToast('출입 신청이 승인되었습니다.', 'success'); await loadRequests(); updateStats(); } else { throw new Error(response?.message || '승인 실패'); } } catch (error) { console.error('승인 처리 오류:', error); showToast(error.message || '승인 처리 중 오류가 발생했습니다.', 'error'); } } /** * 반려 모달 열기 */ function openRejectModal(requestId) { currentRejectRequestId = requestId; document.getElementById('rejectionReason').value = ''; document.getElementById('rejectModal').style.display = 'flex'; } /** * 반려 모달 닫기 */ function closeRejectModal() { currentRejectRequestId = null; document.getElementById('rejectModal').style.display = 'none'; } /** * 반려 확정 */ async function confirmReject() { const reason = document.getElementById('rejectionReason').value.trim(); if (!reason) { showToast('반려 사유를 입력해주세요.', 'warning'); return; } try { const response = await window.apiCall( `/workplace-visits/requests/${currentRejectRequestId}/reject`, 'PUT', { rejection_reason: reason } ); if (response && response.success) { showToast('출입 신청이 반려되었습니다.', 'success'); closeRejectModal(); await loadRequests(); updateStats(); } else { throw new Error(response?.message || '반려 실패'); } } catch (error) { console.error('반려 처리 오류:', error); showToast(error.message || '반려 처리 중 오류가 발생했습니다.', 'error'); } } // ==================== 안전교육 진행 ==================== /** * 안전교육 진행 페이지로 이동 */ function startTraining(requestId) { window.location.href = `/pages/safety/training-conduct.html?request_id=${requestId}`; } // 전역 함수로 노출 window.switchTab = switchTab; window.viewDetail = viewDetail; window.closeDetailModal = closeDetailModal; window.approveRequest = approveRequest; window.openRejectModal = openRejectModal; window.closeRejectModal = closeRejectModal; window.confirmReject = confirmReject; window.startTraining = startTraining;