From a73dd76e70dea3aa0770c214005e42d3fff6c1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=ED=83=9C=ED=9B=88?= Date: Thu, 25 Jun 2026 13:58:25 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=9E=90=EC=82=B0=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?/=EC=88=98=EC=A0=95=20=EB=AA=A8=EB=8B=AC=EC=97=90=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EC=9E=90=EB=8F=99=EC=99=84=EC=84=B1(?= =?UTF-8?q?=EC=82=AC=EB=B2=88,=20=EC=A7=81=EA=B8=89,=20=EB=B6=80=EC=84=9C?= =?UTF-8?q?=20=EC=9E=90=EB=8F=99=20=EC=97=B0=EA=B3=84)=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Modal/HWModal.ts | 94 ++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/src/components/Modal/HWModal.ts b/src/components/Modal/HWModal.ts index 815699c..ec0b4e6 100644 --- a/src/components/Modal/HWModal.ts +++ b/src/components/Modal/HWModal.ts @@ -110,9 +110,14 @@ class HwAssetModal extends BaseModal { -
+
- + + +
+
+ +
@@ -286,6 +291,7 @@ class HwAssetModal extends BaseModal { this.bindAutocomplete('hw-cpu', 'hw-cpu-list', 'CPU'); this.bindAutocomplete('hw-ram', 'hw-ram-list', 'RAM'); this.bindAutocomplete('hw-gpu', 'hw-gpu-list', 'GPU'); + this.bindUserAutocomplete(); }); categorySelect.addEventListener('change', () => { @@ -604,6 +610,7 @@ class HwAssetModal extends BaseModal { setFieldValue('hw-manager_primary', asset.manager_primary || ''); setFieldValue('hw-manager_secondary', asset.manager_secondary || ''); setFieldValue('hw-user_current', asset.user_current || ''); + setFieldValue('hw-emp_no', asset.emp_no || ''); setFieldValue('hw-user_position', asset.user_position || ''); setFieldValue('hw-previous_user', asset.previous_user || ''); setFieldValue('hw-model_name', asset.model_name || ''); @@ -958,6 +965,89 @@ class HwAssetModal extends BaseModal { overlay.querySelector('#btn-preview-close')?.addEventListener('click', () => overlay.remove()); } + private bindUserAutocomplete() { + const input = document.getElementById('hw-user_current') as HTMLInputElement; + const list = document.getElementById('hw-user-current-list') as HTMLDivElement; + const deptSelect = document.getElementById('hw-current_dept') as HTMLSelectElement; + const positionInput = document.getElementById('hw-user_position') as HTMLInputElement; + const empNoInput = document.getElementById('hw-emp_no') as HTMLInputElement; + + if (!input || !list) return; + + const showList = (filterText: string = '') => { + if (!this.isEditMode) return; + const users = state.masterData.users || []; + const query = filterText.trim().toLowerCase(); + + const filtered = query + ? users.filter((u: any) => + u.user_name.toLowerCase().includes(query) || + (u.dept_name && u.dept_name.toLowerCase().includes(query)) || + (u.emp_no && u.emp_no.toLowerCase().includes(query)) + ) + : users; + + if (filtered.length === 0) { + list.innerHTML = '
일치하는 사원 없음
'; + } else { + const seen = new Set(); + const uniqueFiltered = filtered.filter((u: any) => { + const key = `${u.user_name}-${u.dept_name}-${u.emp_no}`; + if (seen.has(key)) return false; + seen.add(key); + return true; + }).slice(0, 15); + + list.innerHTML = uniqueFiltered.map((u: any) => ` +
+
${u.user_name}
+
+ ${u.dept_name || '부서 없음'} / 사번: ${u.emp_no || '-'} / ${u.position || '직급 없음'} +
+
+ `).join(''); + } + list.classList.remove('hidden'); + }; + + input.addEventListener('focus', () => showList(input.value)); + input.addEventListener('input', () => showList(input.value)); + + list.addEventListener('mousedown', (e) => { + const item = (e.target as HTMLElement).closest('.user-suggestion-item'); + if (item) { + const name = item.getAttribute('data-name') || ''; + const dept = item.getAttribute('data-dept') || ''; + const pos = item.getAttribute('data-pos') || ''; + const emp = item.getAttribute('data-emp') || ''; + + input.value = name; + if (positionInput) positionInput.value = pos; + if (empNoInput) empNoInput.value = emp; + + if (deptSelect && dept) { + for (let i = 0; i < deptSelect.options.length; i++) { + if (deptSelect.options[i].value === dept) { + deptSelect.selectedIndex = i; + break; + } + } + } + list.classList.add('hidden'); + } + }); + + document.addEventListener('mousedown', (e) => { + if (e.target !== input && !list.contains(e.target as Node)) { + list.classList.add('hidden'); + } + }); + } + private renderHistory(assetId: string) { const container = document.getElementById('hw-history-list'); if (!container) return;