Files
ITAM-test/src/components/Modal/SWUserModal.ts

250 lines
9.6 KiB
TypeScript

import { state } from '../../core/state';
import { SoftwareAsset, SWUser } from '../../core/excelHandler';
import { openModal } from './BaseModal';
import { createIcons, Edit2, X, Paperclip } from 'lucide';
import { CORP_LIST, ORG_LIST } from './SharedData';
import { generateOptionsHTML, setFieldValue, getFieldValue } from './ModalUtils';
let currentSwUserAsset: SoftwareAsset | null = null;
let tempSwUsers: SWUser[] = [];
const SW_USER_MODAL_HTML = `
<div id="sw-user-modal" class="modal-overlay hidden">
<div class="modal-content wide">
<div class="modal-header">
<h2 id="sw-user-title">소프트웨어 사용자 관리</h2>
<button id="btn-close-sw-user-modal" class="btn-icon"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
<div class="sw-info-summary" id="sw-user-sw-info"></div>
<div class="user-list-toolbar" style="display:flex; justify-content:space-between; margin-bottom:1rem; align-items:center;">
<h3 style="font-size:1rem; font-weight:600;">할당된 사용자 목록</h3>
<button type="button" id="btn-open-add-user" class="btn btn-primary btn-sm"><i data-lucide="plus"></i> 사용자 추가</button>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>구매법인</th>
<th>부서/팀</th>
<th>직위</th>
<th>이름</th>
<th>사용기간</th>
<th>신청서</th>
<th>관리</th>
</tr>
</thead>
<tbody id="sw-user-table-body"></tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button id="btn-cancel-sw-user" class="btn btn-outline">취소</button>
<button id="btn-save-sw-user" class="btn btn-primary">저장</button>
</div>
</div>
</div>
<!-- 사용자 추가/수정 서브 모달 -->
<div id="sw-user-edit-modal" class="modal-overlay hidden" style="z-index:1100;">
<div class="modal-content" style="width:400px;">
<div class="modal-header">
<h3 id="sw-user-edit-title">사용자 정보</h3>
<button id="btn-close-user-edit" class="btn-icon"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
<form id="sw-user-edit-form" class="grid-form" style="grid-template-columns: 1fr;">
<input type="hidden" id="edit-user-index" value="-1" />
<div class="form-group">
<label>구매법인</label>
<select id="new-user-법인">${generateOptionsHTML(CORP_LIST)}</select>
</div>
<div class="form-group">
<label>부서/팀</label>
<select id="new-user-부서">${generateOptionsHTML(ORG_LIST)}</select>
</div>
<div class="form-group">
<label>직위</label>
<input type="text" id="new-user-직위" />
</div>
<div class="form-group">
<label>이름</label>
<input type="text" id="new-user-이름" required />
</div>
<div class="form-group">
<label>사용기간</label>
<input type="text" id="new-user-사용기간" placeholder="ex) 2024-01-01 ~ 2024-12-31" />
</div>
<div class="form-group">
<label>신청서 (증빙)</label>
<input type="file" id="new-user-신청서" />
</div>
</form>
</div>
<div class="modal-footer">
<button id="btn-close-user-sub" class="btn btn-outline">취소</button>
<button id="btn-confirm-user-edit" class="btn btn-primary">확인</button>
</div>
</div>
</div>
`;
export function openSwUserModal(asset: SoftwareAsset) {
currentSwUserAsset = asset;
const modal = document.getElementById('sw-user-modal')!;
const swInfo = document.getElementById('sw-user-sw-info')!;
swInfo.innerHTML = `
<div style="background:var(--bg-light); padding:1rem; border-radius:6px; margin-bottom:1.5rem;">
<div style="font-size:0.8rem; color:var(--text-muted); margin-bottom:0.25rem;">${asset.} | ${asset.}</div>
<div style="font-size:1.1rem; font-weight:700; color:var(--primary-color);">${asset.}</div>
</div>
`;
// 기존 사용자 데이터 복사 (원본 보호를 위해 temp 사용)
const existingMapping = state.masterData.swUsers.find(u => u.sw_id === asset.id);
tempSwUsers = existingMapping ? JSON.parse(JSON.stringify(existingMapping.userDataList || [])) : [];
renderUserList();
modal.classList.remove('hidden');
createIcons({ icons: { Edit2, X, Paperclip } });
}
function renderUserList() {
const tbody = document.getElementById('sw-user-table-body')!;
tbody.innerHTML = '';
if (tempSwUsers.length === 0) {
tbody.innerHTML = '<tr><td colspan="7" style="text-align:center; padding:2rem; color:var(--text-muted);">할당된 사용자가 없습니다.</td></tr>';
return;
}
tempSwUsers.forEach((user, idx) => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${user. || user. || ''}</td>
<td>${user. || ''}</td>
<td>${user. || ''}</td>
<td>${user. || ''}</td>
<td>${user. || ''}</td>
<td style="text-align:center;">${user. ? '<i data-lucide="paperclip" class="text-primary"></i>' : '-'}</td>
<td>
<div style="display:flex; gap:0.5rem;">
<button class="btn btn-outline btn-sm btn-edit-user" data-idx="${idx}">수정</button>
<button class="btn btn-outline btn-sm btn-danger btn-del-user" data-idx="${idx}">삭제</button>
</div>
`;
tbody.appendChild(tr);
});
// 이벤트 연결
tbody.querySelectorAll('.btn-edit-user').forEach(btn => {
btn.addEventListener('click', (e) => {
const idx = parseInt((e.currentTarget as HTMLElement).getAttribute('data-idx')!);
openUserEditSubModal(idx);
});
});
tbody.querySelectorAll('.btn-del-user').forEach(btn => {
btn.addEventListener('click', (e) => {
const idx = parseInt((e.currentTarget as HTMLElement).getAttribute('data-idx')!);
if (confirm('사용자 할당을 삭제하시겠습니까?')) {
tempSwUsers.splice(idx, 1);
renderUserList();
}
});
});
createIcons({ icons: { Paperclip } });
}
function openUserEditSubModal(idx: number = -1) {
const subModal = document.getElementById('sw-user-edit-modal')!;
const form = document.getElementById('sw-user-edit-form') as HTMLFormElement;
form.reset();
setFieldValue('edit-user-index', idx);
if (idx > -1) {
const user = tempSwUsers[idx];
setFieldValue('new-user-법인', user. || user.);
setFieldValue('new-user-부서', user.);
setFieldValue('new-user-직위', user.);
setFieldValue('new-user-이름', user.);
setFieldValue('new-user-사용기간', user.);
} else {
setFieldValue('new-user-법인', currentSwUserAsset?.);
}
subModal.classList.remove('hidden');
}
export function initSwUserModal(onSave: () => void, closeModals: () => void) {
if (!document.getElementById('sw-user-modal')) {
document.body.insertAdjacentHTML('beforeend', SW_USER_MODAL_HTML);
}
const mainSaveBtn = document.getElementById('btn-save-sw-user')!;
const addUserBtn = document.getElementById('btn-open-add-user')!;
const confirmUserBtn = document.getElementById('btn-confirm-user-edit')!;
addUserBtn.addEventListener('click', () => openUserEditSubModal());
confirmUserBtn.addEventListener('click', () => {
saveUserDataToList();
});
mainSaveBtn.addEventListener('click', () => {
if (!currentSwUserAsset) return;
// 전역 상태 업데이트
const existingIdx = state.masterData.swUsers.findIndex(u => u.sw_id === currentSwUserAsset!.id);
const newMapping = {
sw_id: currentSwUserAsset!.id,
userDataList: tempSwUsers
};
if (existingIdx > -1) state.masterData.swUsers[existingIdx] = newMapping as any;
else state.masterData.swUsers.push(newMapping as any);
onSave();
document.getElementById('sw-user-modal')?.classList.add('hidden');
});
document.getElementById('btn-close-sw-user-modal')?.addEventListener('click', () => {
document.getElementById('sw-user-modal')?.classList.add('hidden');
});
document.getElementById('btn-cancel-sw-user')?.addEventListener('click', () => {
document.getElementById('sw-user-modal')?.classList.add('hidden');
});
document.getElementById('btn-close-user-edit')?.addEventListener('click', () => {
document.getElementById('sw-user-edit-modal')?.classList.add('hidden');
});
document.getElementById('btn-close-user-sub')?.addEventListener('click', () => {
document.getElementById('sw-user-edit-modal')?.classList.add('hidden');
});
}
function saveUserDataToList() {
const idx = parseInt(getFieldValue('edit-user-index'));
const Input = document.getElementById('new-user-신청서') as HTMLInputElement;
const = Input.files && Input.files.length > 0 ? Input.files[0].name : (idx > -1 ? tempSwUsers[idx]. : '');
const userData: any = {
구매법인: getFieldValue('new-user-법인'),
부서: getFieldValue('new-user-부서'),
직위: getFieldValue('new-user-직위'),
이름: getFieldValue('new-user-이름'),
사용기간: getFieldValue('new-user-사용기간'),
};
if (idx === -1) tempSwUsers.push(userData);
else tempSwUsers[idx] = userData;
document.getElementById('sw-user-edit-modal')?.classList.add('hidden');
renderUserList();
}