// admin-settings.js - 관리자 설정 페이지 // 전역 변수 let currentUser = null; let users = []; let filteredUsers = []; let currentEditingUser = null; // DOM 요소 const elements = { // 시간 timeValue: document.getElementById('timeValue'), // 사용자 정보 userName: document.getElementById('userName'), userRole: document.getElementById('userRole'), userInitial: document.getElementById('userInitial'), // 검색 및 필터 userSearch: document.getElementById('userSearch'), filterButtons: document.querySelectorAll('.filter-btn'), // 테이블 usersTableBody: document.getElementById('usersTableBody'), emptyState: document.getElementById('emptyState'), // 버튼 addUserBtn: document.getElementById('addUserBtn'), saveUserBtn: document.getElementById('saveUserBtn'), confirmDeleteBtn: document.getElementById('confirmDeleteBtn'), // 모달 userModal: document.getElementById('userModal'), deleteModal: document.getElementById('deleteModal'), modalTitle: document.getElementById('modalTitle'), // 폼 userForm: document.getElementById('userForm'), userNameInput: document.getElementById('userName'), userIdInput: document.getElementById('userId'), userPasswordInput: document.getElementById('userPassword'), userRoleSelect: document.getElementById('userRole'), userEmailInput: document.getElementById('userEmail'), userPhoneInput: document.getElementById('userPhone'), passwordGroup: document.getElementById('passwordGroup'), // 토스트 toastContainer: document.getElementById('toastContainer') }; // ========== 초기화 ========== // document.addEventListener('DOMContentLoaded', async () => { console.log('🔧 관리자 설정 페이지 초기화 시작'); try { await initializePage(); console.log('✅ 관리자 설정 페이지 초기화 완료'); } catch (error) { console.error('❌ 페이지 초기화 오류:', error); showToast('페이지를 불러오는 중 오류가 발생했습니다.', 'error'); } }); async function initializePage() { // 이벤트 리스너 설정 setupEventListeners(); // 사용자 목록 로드 await loadUsers(); } // ========== 사용자 정보 설정 ========== // function setupUserInfo() { const authData = getAuthData(); if (authData && authData.user) { currentUser = authData.user; // 사용자 이름 설정 if (elements.userName) { elements.userName.textContent = currentUser.name || currentUser.username; } // 사용자 역할 설정 const roleMap = { 'admin': '관리자', 'system': '시스템 관리자', 'leader': '그룹장', 'user': '작업자' }; if (elements.userRole) { elements.userRole.textContent = roleMap[currentUser.role] || '작업자'; } // 아바타 초기값 설정 if (elements.userInitial) { const initial = (currentUser.name || currentUser.username).charAt(0); elements.userInitial.textContent = initial; } console.log('👤 사용자 정보 설정 완료:', currentUser.name); } } function getAuthData() { const token = localStorage.getItem('token'); const user = localStorage.getItem('user'); return { token, user: user ? JSON.parse(user) : null }; } // ========== 시간 업데이트 ========== // function updateCurrentTime() { const now = new Date(); const timeString = now.toLocaleTimeString('ko-KR', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' }); if (elements.timeValue) { elements.timeValue.textContent = timeString; } } // ========== 이벤트 리스너 ========== // function setupEventListeners() { // 검색 if (elements.userSearch) { elements.userSearch.addEventListener('input', handleSearch); } // 필터 버튼 elements.filterButtons.forEach(btn => { btn.addEventListener('click', handleFilter); }); // 사용자 추가 버튼 if (elements.addUserBtn) { elements.addUserBtn.addEventListener('click', openAddUserModal); } // 사용자 저장 버튼 if (elements.saveUserBtn) { elements.saveUserBtn.addEventListener('click', saveUser); } // 삭제 확인 버튼 if (elements.confirmDeleteBtn) { elements.confirmDeleteBtn.addEventListener('click', confirmDeleteUser); } // 로그아웃 버튼 const logoutBtn = document.getElementById('logoutBtn'); if (logoutBtn) { logoutBtn.addEventListener('click', handleLogout); } // 프로필 드롭다운 const userProfile = document.getElementById('userProfile'); const profileMenu = document.getElementById('profileMenu'); if (userProfile && profileMenu) { userProfile.addEventListener('click', (e) => { e.stopPropagation(); profileMenu.style.display = profileMenu.style.display === 'block' ? 'none' : 'block'; }); document.addEventListener('click', () => { profileMenu.style.display = 'none'; }); } } // ========== 사용자 관리 ========== // async function loadUsers() { try { console.log('👥 사용자 목록 로딩...'); // 실제 API에서 사용자 데이터 가져오기 const response = await window.apiCall('/users'); users = Array.isArray(response) ? response : (response.data || []); console.log(`✅ 사용자 ${users.length}명 로드 완료`); // 필터링된 사용자 목록 초기화 filteredUsers = [...users]; // 테이블 렌더링 renderUsersTable(); } catch (error) { console.error('❌ 사용자 목록 로딩 오류:', error); showToast('사용자 목록을 불러오는 중 오류가 발생했습니다.', 'error'); users = []; filteredUsers = []; renderUsersTable(); } } function renderUsersTable() { if (!elements.usersTableBody) return; if (filteredUsers.length === 0) { elements.usersTableBody.innerHTML = ''; if (elements.emptyState) { elements.emptyState.style.display = 'block'; } return; } if (elements.emptyState) { elements.emptyState.style.display = 'none'; } elements.usersTableBody.innerHTML = filteredUsers.map(user => `
${(user.name || user.username).charAt(0)}

${user.name || user.username}

${user.email || '이메일 없음'}

${user.username} ${getRoleIcon(user.role)} ${getRoleName(user.role)} ${user.is_active ? '활성' : '비활성'} ${formatDate(user.last_login) || '로그인 기록 없음'}
`).join(''); } function getRoleIcon(role) { const icons = { admin: '👑', leader: '👨‍💼', user: '👤' }; return icons[role] || '👤'; } function getRoleName(role) { const names = { admin: '관리자', leader: '그룹장', user: '작업자' }; return names[role] || '작업자'; } function formatDate(dateString) { if (!dateString) return null; const date = new Date(dateString); return date.toLocaleDateString('ko-KR', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); } // ========== 검색 및 필터링 ========== // function handleSearch(e) { const searchTerm = e.target.value.toLowerCase(); filteredUsers = users.filter(user => { return (user.name && user.name.toLowerCase().includes(searchTerm)) || (user.username && user.username.toLowerCase().includes(searchTerm)) || (user.email && user.email.toLowerCase().includes(searchTerm)); }); renderUsersTable(); } function handleFilter(e) { const filterType = e.target.dataset.filter; // 활성 버튼 변경 elements.filterButtons.forEach(btn => btn.classList.remove('active')); e.target.classList.add('active'); // 필터링 if (filterType === 'all') { filteredUsers = [...users]; } else { filteredUsers = users.filter(user => user.role === filterType); } renderUsersTable(); } // ========== 모달 관리 ========== // function openAddUserModal() { currentEditingUser = null; if (elements.modalTitle) { elements.modalTitle.textContent = '새 사용자 추가'; } // 폼 초기화 if (elements.userForm) { elements.userForm.reset(); } // 비밀번호 필드 표시 if (elements.passwordGroup) { elements.passwordGroup.style.display = 'block'; } if (elements.userPasswordInput) { elements.userPasswordInput.required = true; } if (elements.userModal) { elements.userModal.style.display = 'flex'; } } function editUser(userId) { const user = users.find(u => u.user_id === userId); if (!user) return; currentEditingUser = user; if (elements.modalTitle) { elements.modalTitle.textContent = '사용자 정보 수정'; } // 폼에 데이터 채우기 if (elements.userNameInput) elements.userNameInput.value = user.name || ''; if (elements.userIdInput) elements.userIdInput.value = user.username || ''; if (elements.userRoleSelect) elements.userRoleSelect.value = user.role || ''; if (elements.userEmailInput) elements.userEmailInput.value = user.email || ''; if (elements.userPhoneInput) elements.userPhoneInput.value = user.phone || ''; // 비밀번호 필드 숨기기 (수정 시에는 선택사항) if (elements.passwordGroup) { elements.passwordGroup.style.display = 'none'; } if (elements.userPasswordInput) { elements.userPasswordInput.required = false; } if (elements.userModal) { elements.userModal.style.display = 'flex'; } } function closeUserModal() { if (elements.userModal) { elements.userModal.style.display = 'none'; } currentEditingUser = null; } function deleteUser(userId) { const user = users.find(u => u.user_id === userId); if (!user) return; currentEditingUser = user; if (elements.deleteModal) { elements.deleteModal.style.display = 'flex'; } } function closeDeleteModal() { if (elements.deleteModal) { elements.deleteModal.style.display = 'none'; } currentEditingUser = null; } // ========== 사용자 CRUD ========== // async function saveUser() { try { const formData = { name: elements.userNameInput?.value, username: elements.userIdInput?.value, role: elements.userRoleSelect?.value, email: elements.userEmailInput?.value, phone: elements.userPhoneInput?.value }; // 유효성 검사 if (!formData.name || !formData.username || !formData.role) { showToast('필수 항목을 모두 입력해주세요.', 'error'); return; } // 비밀번호 처리 if (!currentEditingUser && elements.userPasswordInput?.value) { formData.password = elements.userPasswordInput.value; } else if (currentEditingUser && elements.userPasswordInput?.value) { formData.password = elements.userPasswordInput.value; } let response; if (currentEditingUser) { // 수정 response = await window.apiCall(`/users/${currentEditingUser.user_id}`, 'PUT', formData); } else { // 생성 response = await window.apiCall('/users', 'POST', formData); } if (response.success || response.user_id) { const action = currentEditingUser ? '수정' : '생성'; showToast(`사용자가 성공적으로 ${action}되었습니다.`, 'success'); closeUserModal(); await loadUsers(); } else { throw new Error(response.message || '사용자 저장에 실패했습니다.'); } } catch (error) { console.error('사용자 저장 오류:', error); showToast(`사용자 저장 중 오류가 발생했습니다: ${error.message}`, 'error'); } } async function confirmDeleteUser() { if (!currentEditingUser) return; try { const response = await window.apiCall(`/users/${currentEditingUser.user_id}`, 'DELETE'); if (response.success) { showToast('사용자가 성공적으로 삭제되었습니다.', 'success'); closeDeleteModal(); await loadUsers(); } else { throw new Error(response.message || '사용자 삭제에 실패했습니다.'); } } catch (error) { console.error('사용자 삭제 오류:', error); showToast(`사용자 삭제 중 오류가 발생했습니다: ${error.message}`, 'error'); } } async function toggleUserStatus(userId) { try { const user = users.find(u => u.user_id === userId); if (!user) return; const newStatus = !user.is_active; const response = await window.apiCall(`/users/${userId}/status`, 'PUT', { is_active: newStatus }); if (response.success) { const action = newStatus ? '활성화' : '비활성화'; showToast(`사용자가 성공적으로 ${action}되었습니다.`, 'success'); await loadUsers(); } else { throw new Error(response.message || '사용자 상태 변경에 실패했습니다.'); } } catch (error) { console.error('사용자 상태 변경 오류:', error); showToast(`사용자 상태 변경 중 오류가 발생했습니다: ${error.message}`, 'error'); } } // ========== 로그아웃 ========== // function handleLogout() { if (confirm('로그아웃하시겠습니까?')) { localStorage.clear(); window.location.href = '/index.html'; } } // ========== 토스트 알림 ========== // function showToast(message, type = 'info', duration = 3000) { if (!elements.toastContainer) return; const toast = document.createElement('div'); toast.className = `toast ${type}`; const iconMap = { success: '✅', error: '❌', warning: '⚠️', info: 'ℹ️' }; toast.innerHTML = `
${iconMap[type] || 'ℹ️'}
${message}
`; elements.toastContainer.appendChild(toast); // 자동 제거 setTimeout(() => { if (toast.parentElement) { toast.remove(); } }, duration); } // ========== 전역 함수 (HTML에서 호출) ========== // window.editUser = editUser; window.deleteUser = deleteUser; window.toggleUserStatus = toggleUserStatus; window.closeUserModal = closeUserModal; window.closeDeleteModal = closeDeleteModal;