189 lines
8.4 KiB
TypeScript
189 lines
8.4 KiB
TypeScript
import { state, saveAsset, deleteAsset } from '../../core/state';
|
|
import { BaseModal } from './BaseModal';
|
|
import { CORP_LIST } from './SharedData';
|
|
import { generateOptionsHTML, setFieldValue, getFieldValue } from './ModalUtils';
|
|
import { createIcons, X, Save, Database, CalendarClock, Edit2, History, Plus } from 'lucide';
|
|
import { formatExcelDate } from '../../core/excelHandler';
|
|
import { UI_TEXT } from '../../core/schema';
|
|
|
|
class DomainAssetModal extends BaseModal {
|
|
constructor() {
|
|
super('domain', '도메인 정보');
|
|
}
|
|
|
|
protected renderFrameHTML(): string {
|
|
return `
|
|
<div id="domain-asset-modal" class="modal-overlay hidden">
|
|
<div class="modal-content wide">
|
|
<div class="modal-header">
|
|
<h2 id="domain-modal-title">${this.title}</h2>
|
|
<button id="btn-close-domain-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="modal-body-split">
|
|
<div class="modal-form-area">
|
|
<form id="domain-asset-form" class="grid-form">
|
|
<input type="hidden" id="domain-id" name="id" />
|
|
|
|
<div class="form-section-title">기본 정보</div>
|
|
<div class="form-group">
|
|
<label>구분</label>
|
|
<select id="domain-type" name="type">
|
|
<option value="호스팅">호스팅</option>
|
|
<option value="도메인">도메인</option>
|
|
<option value="기타">기타</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>관리법인</label>
|
|
<select id="domain-corp" name="corp">${generateOptionsHTML(CORP_LIST)}</select>
|
|
</div>
|
|
<div class="form-group full-width">
|
|
<label>서비스명</label>
|
|
<input type="text" id="domain-service-name" name="service_name" required />
|
|
</div>
|
|
<div class="form-group full-width">
|
|
<label>관리도메인</label>
|
|
<input type="text" id="domain-name" name="domain_name" required />
|
|
</div>
|
|
|
|
<div class="form-section-title">계약 및 비용</div>
|
|
<div class="form-group">
|
|
<label>계약시작일</label>
|
|
<input type="date" id="domain-start-date" name="start_date" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label>만료예정일</label>
|
|
<input type="date" id="domain-expiry-date" name="expiry_date" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label>비용 (연간/월간)</label>
|
|
<input type="text" id="domain-price" name="price" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\\\B(?=(\\\\d{3})+(?!\\\\d))/g, ',')" />
|
|
</div>
|
|
|
|
<div class="form-section-title">담당자 및 비고</div>
|
|
<div class="form-group">
|
|
<label>정담당자</label>
|
|
<input type="text" id="domain-manager-main" name="manager_main" />
|
|
</div>
|
|
<div class="form-group">
|
|
<label>부담당자</label>
|
|
<input type="text" id="domain-manager-sub" name="manager_sub" />
|
|
</div>
|
|
<div class="form-group full-width">
|
|
<label>비고</label>
|
|
<textarea id="domain-remarks" name="remarks" rows="3"></textarea>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-history-area">
|
|
<div class="history-header">
|
|
<h3><i data-lucide="history" style="width:16px; height:16px;"></i> 변경 이력</h3>
|
|
<button type="button" id="btn-add-domain-log" class="btn btn-outline btn-sm">
|
|
이력 추가 <i data-lucide="plus" style="width:14px; height:14px;"></i>
|
|
</button>
|
|
</div>
|
|
<div id="domain-history-list" class="history-timeline"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button id="btn-delete-domain-asset" class="btn btn-outline btn-danger">삭제</button>
|
|
<div class="footer-actions">
|
|
<button id="btn-revert-domain-edit" class="btn btn-outline hidden">수정 취소</button>
|
|
<button id="btn-cancel-domain-modal" class="btn btn-outline">닫기</button>
|
|
<button id="btn-save-domain-asset" class="btn btn-primary">수정</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
protected initChildLogic(onSave: () => void, closeModals: () => void): void {
|
|
const saveBtn = document.getElementById('btn-save-domain-asset')!;
|
|
const revertBtn = document.getElementById('btn-revert-domain-edit')!;
|
|
const deleteBtn = document.getElementById('btn-delete-domain-asset')!;
|
|
|
|
saveBtn.addEventListener('click', async () => {
|
|
if (!this.currentAsset) return;
|
|
if (!this.isEditMode) {
|
|
this.setEditLockMode('edit');
|
|
this.isEditMode = true;
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData(this.formEl!);
|
|
const updated = { ...this.currentAsset };
|
|
formData.forEach((value, key) => { updated[key] = value; });
|
|
|
|
if (!updated.service_name || !updated.domain_name) {
|
|
alert('서비스명과 관리도메인은 필수 입력 사항입니다.');
|
|
return;
|
|
}
|
|
|
|
if (await saveAsset('domain', updated)) {
|
|
alert(UI_TEXT.MESSAGES.SAVE_SUCCESS);
|
|
onSave(); this.close(); closeModals();
|
|
}
|
|
});
|
|
|
|
revertBtn.addEventListener('click', () => {
|
|
this.setEditLockMode('view');
|
|
if (this.currentAsset) this.fillFormData(this.currentAsset);
|
|
});
|
|
|
|
deleteBtn.addEventListener('click', async () => {
|
|
if (!this.currentAsset || !confirm(UI_TEXT.MESSAGES.CONFIRM_DELETE)) return;
|
|
if (await deleteAsset('domain', this.currentAsset.id)) {
|
|
alert('성공적으로 삭제되었습니다.');
|
|
onSave(); this.close(); closeModals();
|
|
}
|
|
});
|
|
|
|
createIcons({ icons: { History, Plus, Save, CalendarClock, Database } });
|
|
}
|
|
|
|
protected fillFormData(asset: any): void {
|
|
setFieldValue('domain-id', asset.id);
|
|
setFieldValue('domain-type', asset.type || '호스팅');
|
|
setFieldValue('domain-corp', asset.corp || '');
|
|
setFieldValue('domain-service-name', asset.service_name || '');
|
|
setFieldValue('domain-name', asset.domain_name || '');
|
|
setFieldValue('domain-start-date', formatExcelDate(asset.start_date));
|
|
setFieldValue('domain-expiry-date', formatExcelDate(asset.expiry_date));
|
|
setFieldValue('domain-price', asset.price || '');
|
|
setFieldValue('domain-manager-main', asset.manager_main || '');
|
|
setFieldValue('domain-manager-sub', asset.manager_sub || '');
|
|
setFieldValue('domain-remarks', asset.remarks || '');
|
|
|
|
this.renderHistory(asset.id);
|
|
}
|
|
|
|
protected onAfterOpen(asset: any, mode: string): void {
|
|
const titleEl = document.getElementById('domain-modal-title');
|
|
if (titleEl) titleEl.textContent = (mode === 'add') ? '신규 도메인 등록' : '도메인 정보 상세';
|
|
|
|
const deleteBtn = document.getElementById('btn-delete-domain-asset');
|
|
if (deleteBtn) deleteBtn.style.display = (mode === 'add') ? 'none' : 'block';
|
|
}
|
|
|
|
private renderHistory(assetId: string) {
|
|
const container = document.getElementById('domain-history-list');
|
|
if (!container) return;
|
|
const logs = (state.masterData.logs || []).filter(l => l.assetId === assetId);
|
|
if (logs.length === 0) { container.innerHTML = '<div class="empty-history">이력이 없습니다.</div>'; return; }
|
|
container.innerHTML = logs.map(l => `<div class=\"history-item\"><div class=\"history-date\">${l.date}</div><div class=\"history-user\">${l.user}</div><div class=\"history-details\">${l.details}</div></div>`).join('');
|
|
}
|
|
}
|
|
|
|
export const domainModal = new DomainAssetModal();
|
|
|
|
export function initDomainModal(onSave: () => void, closeModals: () => void) {
|
|
domainModal.init(onSave, closeModals);
|
|
}
|
|
|
|
export function openDomainModal(asset: any, mode: 'view' | 'edit' | 'add' = 'view') {
|
|
domainModal.open(asset, mode);
|
|
}
|