diff --git a/user-management/web/index.html b/user-management/web/index.html index 4b37fa1..3ba0192 100644 --- a/user-management/web/index.html +++ b/user-management/web/index.html @@ -149,7 +149,16 @@
-

사용자 목록

+

+ 사용자 목록 + +

+
+ + +

로딩 중...

@@ -2351,7 +2360,7 @@ - + diff --git a/user-management/web/static/js/tkuser-users.js b/user-management/web/static/js/tkuser-users.js index 857da72..54b5792 100644 --- a/user-management/web/static/js/tkuser-users.js +++ b/user-management/web/static/js/tkuser-users.js @@ -112,7 +112,7 @@ async function loadUsers() { try { const r = await api('/users'); users = r.data || r; displayUsers(); updatePermissionUserSelect(); - populateUserDeptSelects(); + populateUserDeptSelects(); populateUserDeptFilter(); const hireDateInput = document.getElementById('newHireDate'); if (hireDateInput && !hireDateInput.value) hireDateInput.value = getSeoulToday(); } catch (err) { @@ -129,6 +129,15 @@ function populateUserDeptSelects() { sel.value = val; }); } +// 필터용 부서 셀렉트 (populateUserDeptSelects는 모달 폼용) +function populateUserDeptFilter() { + const sel = document.getElementById('userDeptFilter'); + if (!sel) return; + const val = sel.value; + sel.innerHTML = ''; + departmentsCache.forEach(d => { const o = document.createElement('option'); o.value = d.department_id; o.textContent = d.department_name; sel.appendChild(o); }); + sel.value = val; +} function renderUserRow(u, isResigned) { return `
@@ -151,12 +160,38 @@ function renderUserRow(u, isResigned) { } function displayUsers() { - const activeUsers = users.filter(u => u.is_active !== 0 && u.is_active !== false); - const resignedUsers = users.filter(u => u.is_active === 0 || u.is_active === false); + const searchTerm = (document.getElementById('userSearchInput')?.value || '').trim().toLowerCase(); + const deptFilterVal = document.getElementById('userDeptFilter')?.value || ''; + + let filtered = users; + + if (searchTerm) { + filtered = filtered.filter(u => { + const name = (u.name || '').toLowerCase(); + const username = (u.username || '').toLowerCase(); + return name.includes(searchTerm) || username.includes(searchTerm); + }); + } + + if (deptFilterVal) { + const deptId = parseInt(deptFilterVal); + filtered = filtered.filter(u => u.department_id === deptId); + } + + const activeUsers = filtered.filter(u => u.is_active !== 0 && u.is_active !== false); + const resignedUsers = filtered.filter(u => u.is_active === 0 || u.is_active === false); const c = document.getElementById('userList'); - if (!activeUsers.length) { c.innerHTML = '

등록된 사용자가 없습니다.

'; } - else { c.innerHTML = activeUsers.map(u => renderUserRow(u, false)).join(''); } + const countEl = document.getElementById('activeUserCount'); + if (countEl) countEl.textContent = `(${activeUsers.length}명)`; + + if (!activeUsers.length) { + c.innerHTML = searchTerm || deptFilterVal + ? '

검색 결과가 없습니다.

' + : '

등록된 사용자가 없습니다.

'; + } else { + c.innerHTML = activeUsers.map(u => renderUserRow(u, false)).join(''); + } const resignedSection = document.getElementById('resignedSection'); const resignedList = document.getElementById('resignedUserList'); @@ -419,6 +454,16 @@ function populateDeptPermSelect() { } document.addEventListener('DOMContentLoaded', () => { + // 사용자 검색 + 부서 필터 + let userSearchTimeout; + const userSearchEl = document.getElementById('userSearchInput'); + if (userSearchEl) userSearchEl.addEventListener('input', () => { + clearTimeout(userSearchTimeout); + userSearchTimeout = setTimeout(displayUsers, 300); + }); + const userDeptFilterEl = document.getElementById('userDeptFilter'); + if (userDeptFilterEl) userDeptFilterEl.addEventListener('change', displayUsers); + const sel = document.getElementById('deptPermSelect'); if (sel) sel.addEventListener('change', async e => { selectedDeptId = e.target.value;