feat(tkuser): 사용자 목록 검색 + 부서 필터 기능 추가
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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 = '<option value="">전체 부서</option>';
|
||||
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 `<div class="flex items-center justify-between p-2.5 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors">
|
||||
<div class="flex-1 min-w-0">
|
||||
@@ -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 = '<p class="text-gray-400 text-center py-4 text-sm">등록된 사용자가 없습니다.</p>'; }
|
||||
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
|
||||
? '<p class="text-gray-400 text-center py-4 text-sm">검색 결과가 없습니다.</p>'
|
||||
: '<p class="text-gray-400 text-center py-4 text-sm">등록된 사용자가 없습니다.</p>';
|
||||
} 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;
|
||||
|
||||
Reference in New Issue
Block a user