style: 리팩토링 및 CSS 통합 작업 완료 (하드코딩 스타일 제거)

This commit is contained in:
2026-06-12 13:29:59 +09:00
parent f5a84a77ef
commit fd9e88d7c6
38 changed files with 4785 additions and 592 deletions

View File

@@ -4,14 +4,14 @@ import { createIcons, X } from 'lucide';
const DASHBOARD_DETAIL_MODAL_HTML = `
<div id="dashboard-detail-modal" class="modal-overlay hidden">
<div class="modal-content wide" style="max-width: 1000px;">
<div class="modal-content wide">
<div class="modal-header">
<h2 id="dashboard-detail-modal-title">상세 목록</h2>
<h2 id="dashboard-detail-modal-title" class="modal-title">상세 목록</h2>
<button id="btn-close-dashboard-detail-modal" class="btn-icon" aria-label="닫기"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
<div class="table-container">
<table style="width:100%;">
<table>
<thead></thead>
<tbody id="dashboard-detail-tbody"></tbody>
</table>

View File

@@ -19,18 +19,14 @@ class HwAssetModal extends BaseModal {
}
protected renderFrameHTML(): string {
const sharedStyle = 'height: 38px !important; box-sizing: border-box !important; font-size: 13px; margin: 0;';
const inputStyle = sharedStyle;
const btnStyle = `padding: 0 16px; display: inline-flex; align-items: center; justify-content: center; font-weight: 600; white-space: nowrap; cursor: pointer; ${sharedStyle}`;
return `
<div id="hw-asset-modal" class="modal-overlay hidden">
<div class="modal-content wide">
<div class="modal-header">
<h2 id="hw-modal-title" style="margin: 0; font-size: 18px; font-weight: 800; color: white;">${this.title}</h2>
<button id="btn-close-hw-modal" class="btn-icon" aria-label="닫기" style="font-size: 28px; color: white; background: none; border: none; cursor: pointer; line-height: 1;">&times;</button>
<h2 id="hw-modal-title" class="modal-title">${this.title}</h2>
<button id="btn-close-hw-modal" class="btn-icon" aria-label="닫기">&times;</button>
</div>
<div class="modal-body" style="padding: 24px; overflow-y: auto;">
<div class="modal-body">
<div class="modal-body-split">
<div class="modal-form-area">
<form id="hw-asset-form" class="grid-form">
@@ -38,195 +34,195 @@ class HwAssetModal extends BaseModal {
<input type="hidden" id="hw-remotes-data" name="remotes" />
<!-- [SECTION 1] 기본 관리 정보 -->
<div class="form-section-title" style="padding-top: 0; margin-bottom: 12px;">기본 관리 정보</div>
<div class="form-section-title">기본 관리 정보</div>
<div class="form-group">
<label>${ASSET_SCHEMA.ASSET_CODE.ui}</label>
<div class="input-with-btn" style="display: flex; gap: 8px; align-items: stretch;">
<input type="text" id="hw-asset_code" name="asset_code" placeholder="자동 생성" readonly style="flex: 1; ${inputStyle}" />
<button type="button" id="btn-gen-hw-code" class="btn btn-outline" style="${btnStyle}">생성</button>
<div class="input-with-btn">
<input type="text" id="hw-asset_code" name="asset_code" placeholder="자동 생성" readonly />
<button type="button" id="btn-gen-hw-code" class="btn btn-outline">생성</button>
</div>
</div>
<div class="form-group">
<label>${ASSET_SCHEMA.PURCHASE_CORP.ui}</label>
<select id="hw-purchase_corp" name="purchase_corp" style="${inputStyle}">${generateOptionsHTML(CORP_LIST)}</select>
<select id="hw-purchase_corp" name="purchase_corp">${generateOptionsHTML(CORP_LIST)}</select>
</div>
<div class="form-group">
<label>${ASSET_SCHEMA.CATEGORY.ui}</label>
<select id="hw-category" name="category" style="${inputStyle}">
<select id="hw-category" name="category">
<option value="">선택</option>
${generateOptionsHTML(Object.keys(CATEGORY_TYPE_MAP), '', false)}
</select>
</div>
<div class="form-group">
<label>${ASSET_SCHEMA.ASSET_TYPE.ui}</label>
<select id="hw-asset_type" name="asset_type" style="${inputStyle}">
<select id="hw-asset_type" name="asset_type">
<option value="">구분을 먼저 선택하세요</option>
</select>
</div>
<div class="form-group">
<label>${ASSET_SCHEMA.HW_STATUS.ui}</label>
<select id="hw-hw_status" name="hw_status" style="${inputStyle}">${generateOptionsHTML(HW_STATUS_LIST)}</select>
<select id="hw-hw_status" name="hw_status">${generateOptionsHTML(HW_STATUS_LIST)}</select>
</div>
<div class="form-group infra-only monitoring-field">
<label>${ASSET_SCHEMA.MONITORING.ui}</label>
<select id="hw-monitoring" name="monitoring" style="${inputStyle}">
<select id="hw-monitoring" name="monitoring">
<option value="비대상">비대상</option>
<option value="대상">대상</option>
</select>
</div>
<!-- [SECTION 2] 조직 및 사용자 정보 -->
<div class="form-section-title org-user-section" style="margin-top: 24px; margin-bottom: 12px;">사용자 및 조직 정보</div>
<div class="form-section-title org-user-section">사용자 및 조직 정보</div>
<div class="form-group org-user-field">
<label>${ASSET_SCHEMA.CURRENT_DEPT.ui}</label>
<select id="hw-current_dept" name="current_dept" style="${inputStyle}">${generateOptionsHTML(ORG_LIST)}</select>
<select id="hw-current_dept" name="current_dept">${generateOptionsHTML(ORG_LIST)}</select>
</div>
<div class="form-group org-user-field">
<label>${ASSET_SCHEMA.MANAGER_MAIN.ui}</label>
<input type="text" id="hw-manager_primary" name="manager_primary" style="${inputStyle}" />
<input type="text" id="hw-manager_primary" name="manager_primary" />
</div>
<div class="form-group personal-only">
<label>${ASSET_SCHEMA.CURRENT_USER.ui}</label>
<input type="text" id="hw-user_current" name="user_current" style="${inputStyle}" />
<input type="text" id="hw-user_current" name="user_current" />
</div>
<div class="form-group personal-only">
<label>${ASSET_SCHEMA.USER_POSITION.ui}</label>
<input type="text" id="hw-user_position" name="user_position" style="${inputStyle}" />
<input type="text" id="hw-user_position" name="user_position" />
</div>
<div class="form-group">
<label>${ASSET_SCHEMA.MANAGER_SUB.ui}</label>
<input type="text" id="hw-manager_secondary" name="manager_secondary" style="${inputStyle}" />
<input type="text" id="hw-manager_secondary" name="manager_secondary" />
</div>
<div class="form-group personal-only">
<label>${ASSET_SCHEMA.PREV_USER.ui}</label>
<input type="text" id="hw-previous_user" name="previous_user" style="${inputStyle}" />
<input type="text" id="hw-previous_user" name="previous_user" />
</div>
<!-- [SECTION 3] 하드웨어 사양 -->
<div class="form-section-title hardware-section" style="margin-top: 24px; margin-bottom: 12px;">시스템 사양 정보</div>
<div class="form-section-title hardware-section">시스템 사양 정보</div>
<div class="form-group">
<label>${ASSET_SCHEMA.MODEL_NAME.ui}</label>
<input type="text" id="hw-model_name" name="model_name" style="${inputStyle}" />
<input type="text" id="hw-model_name" name="model_name" />
</div>
<div class="form-group">
<label>${ASSET_SCHEMA.ASSET_MFR.ui}</label>
<input type="text" id="hw-asset_mfr" name="asset_mfr" style="${inputStyle}" />
<input type="text" id="hw-asset_mfr" name="asset_mfr" />
</div>
<div class="form-group sn-only">
<label>${ASSET_SCHEMA.SERIAL_NUM.ui}</label>
<input type="text" id="hw-serial_num" name="serial_num" style="${inputStyle}" />
<input type="text" id="hw-serial_num" name="serial_num" />
</div>
<div class="form-group spec-only">
<label>${ASSET_SCHEMA.OS.ui}</label>
<input type="text" id="hw-os" name="os" style="${inputStyle}" />
<input type="text" id="hw-os" name="os" />
</div>
<div class="form-group spec-only">
<label>${ASSET_SCHEMA.CPU.ui}</label>
<input type="text" id="hw-cpu" name="cpu" style="${inputStyle}" />
<input type="text" id="hw-cpu" name="cpu" />
</div>
<div class="form-group spec-only">
<label>${ASSET_SCHEMA.RAM.ui}</label>
<input type="text" id="hw-ram" name="ram" style="${inputStyle}" />
<input type="text" id="hw-ram" name="ram" />
</div>
<div class="form-group spec-only">
<label>${ASSET_SCHEMA.GPU.ui}</label>
<input type="text" id="hw-gpu" name="gpu" style="${inputStyle}" />
<input type="text" id="hw-gpu" name="gpu" />
</div>
<div class="form-group spec-only">
<label>${ASSET_SCHEMA.MAINBOARD.ui}</label>
<input type="text" id="hw-mainboard" name="mainboard" style="${inputStyle}" />
<input type="text" id="hw-mainboard" name="mainboard" />
</div>
<div class="form-group monitor-only">
<label>${ASSET_SCHEMA.MONITOR_INCH.ui}</label>
<input type="text" id="hw-monitor_inch" name="monitor_inch" style="${inputStyle}" />
<input type="text" id="hw-monitor_inch" name="monitor_inch" />
</div>
<!-- 동적 디스크 할당 영역 -->
<div class="form-section-title spec-only" style="margin-top: 24px; margin-bottom: 12px;">디스크(용량) 정보</div>
<div class="form-group spec-only full-width" style="grid-column: span 2;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
<label style="margin: 0; font-size: 11px; font-weight: 700; color: var(--text-muted);">연결된 드라이브 리스트</label>
<button type="button" id="btn-add-volume" class="btn btn-outline" style="height: 26px !important; padding: 0 10px; font-size: 11px; display: none;">+ 볼륨 추가</button>
<div class="form-section-title spec-only">디스크(용량) 정보</div>
<div class="form-group spec-only full-width">
<div class="history-header">
<label>연결된 드라이브 리스트</label>
<button type="button" id="btn-add-volume" class="btn btn-outline btn-sm hidden">+ 볼륨 추가</button>
</div>
<div id="hw-volume-container" style="display: flex; flex-direction: column; gap: 8px;"></div>
<div id="hw-volume-container" class="volume-container"></div>
<input type="hidden" id="hw-volumes-data" name="volumes" />
</div>
<!-- 통합 원격 접속 정보 영역 -->
<div class="form-section-title net-only" style="margin-top: 24px; margin-bottom: 12px;">네트워크 및 원격 접속 정보</div>
<div class="form-group net-only full-width" style="grid-column: span 2;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
<label style="margin: 0; font-size: 11px; font-weight: 700; color: var(--text-muted);">IP/MAC 및 접속 계정 정보</label>
<button type="button" id="btn-add-remote-info" class="btn btn-outline" style="height: 26px !important; padding: 0 10px; font-size: 11px; display: none;">+ 접속 정보 추가</button>
<div class="form-section-title net-only">네트워크 및 원격 접속 정보</div>
<div class="form-group net-only full-width">
<div class="history-header">
<label>IP/MAC 및 접속 계정 정보</label>
<button type="button" id="btn-add-remote-info" class="btn btn-outline btn-sm hidden">+ 접속 정보 추가</button>
</div>
<div id="hw-remote-info-container" style="display: flex; flex-direction: column; gap: 12px;"></div>
<div id="hw-remote-info-container" class="remote-info-container"></div>
</div>
<!-- [SECTION 5] 설치 위치 -->
<div class="form-section-title location-section" style="margin-top: 24px; margin-bottom: 12px;">설치 위치</div>
<div class="form-section-title location-section">설치 위치</div>
<div class="form-group location-field">
<label>건물/위치</label>
<select id="hw-bldg-select" name="location" style="${inputStyle}">${generateOptionsHTML(Object.keys(LOCATION_DATA))}</select>
<select id="hw-bldg-select" name="location">${generateOptionsHTML(Object.keys(LOCATION_DATA))}</select>
</div>
<div class="form-group location-field">
<label>${ASSET_SCHEMA.LOC_DETAIL.ui}</label>
<div class="input-with-btn" style="display: flex; gap: 8px; align-items: stretch;">
<select id="hw-location_detail" name="location_detail" style="flex: 1; ${inputStyle}"><option value="">선택</option></select>
<button type="button" id="btn-reg-loc-map" class="btn btn-primary" style="${btnStyle} display: none;">위치등록</button>
<button type="button" id="btn-view-loc-map" class="btn btn-primary btn-loc-action btn-loc-view" style="${btnStyle} display: none; pointer-events: auto !important; cursor: pointer !important;">위치보기</button>
<div class="input-with-btn">
<select id="hw-location_detail" name="location_detail"><option value="">선택</option></select>
<button type="button" id="btn-reg-loc-map" class="btn btn-primary hidden">위치등록</button>
<button type="button" id="btn-view-loc-map" class="btn btn-primary btn-loc-action btn-loc-view hidden">위치보기</button>
</div>
<input type="hidden" id="hw-loc_x" name="loc_x" /><input type="hidden" id="hw-loc_y" name="loc_y" /><input type="hidden" id="hw-location_photo" name="location_photo" />
</div>
<!-- [SECTION 6] 구매 정보 -->
<div class="form-section-title" style="margin-top: 24px; margin-bottom: 12px;">구매 및 증빙 정보</div>
<div class="form-section-title">구매 및 증빙 정보</div>
<div class="form-group">
<label>${ASSET_SCHEMA.PURCHASE_DATE.ui}</label>
<input type="text" id="hw-purchase_date" name="purchase_date" placeholder="YYYY-MM-DD" style="${inputStyle}" />
<input type="text" id="hw-purchase_date" name="purchase_date" placeholder="YYYY-MM-DD" />
</div>
<div class="form-group">
<label>${ASSET_SCHEMA.PURCHASE_VENDOR.ui}</label>
<input type="text" id="hw-purchase_vendor" name="purchase_vendor" style="${inputStyle}" />
<input type="text" id="hw-purchase_vendor" name="purchase_vendor" />
</div>
<div class="form-group">
<label>${ASSET_SCHEMA.PURCHASE_AMOUNT.ui}</label>
<input type="text" id="hw-purchase_amount" name="purchase_amount" placeholder="0" style="${inputStyle}" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')" />
<input type="text" id="hw-purchase_amount" name="purchase_amount" placeholder="0" oninput="this.value = this.value.replace(/[^0-9]/g, '').replace(/\\\\B(?=(\\\\d{3})+(?!\\\\d))/g, ',')" />
</div>
<div class="form-group">
<label>${ASSET_SCHEMA.APPROVAL_DOC.ui} (첨부파일)</label>
<div class="file-upload-wrapper">
<input type="file" id="hw-approval_document_file" style="display:none;" />
<div class="input-with-btn" style="display: flex; gap: 8px; align-items: stretch;">
<button type="button" id="btn-file-select" onclick="document.getElementById('hw-approval_document_file').click()" class="btn btn-outline btn-loc-action" style="${btnStyle} flex: 1; justify-content: flex-start; pointer-events: auto !important; cursor: pointer !important;">
<div class="input-with-btn">
<button type="button" id="btn-file-select" onclick="document.getElementById('hw-approval_document_file').click()" class="btn btn-outline btn-loc-action">
<span id="hw-file-name-display">파일 선택...</span>
</button>
</div>
<input type="hidden" id="hw-approval_document" name="approval_document" />
<div id="hw-file-link-container" style="margin-top: 4px;"></div>
<div id="hw-file-link-container"></div>
</div>
</div>
<div class="form-group full-width">
<label>${ASSET_SCHEMA.MEMO.ui}</label>
<textarea id="hw-memo" name="memo" rows="3" style="width: 100%; padding: 10px; border: 1px solid var(--border-color); border-radius: 4px; font-family: inherit; font-size: 13px; resize: none !important; box-sizing: border-box;"></textarea>
<textarea id="hw-memo" name="memo" rows="3"></textarea>
</div>
</form>
</div>
<div class="modal-history-area">
<div class="history-header" style="border-bottom: 1px solid var(--border-color); padding-bottom: 12px; margin-bottom: 16px;">
<h3 style="margin: 0; font-size: 14px; font-weight: 800;">자산 변동 이력</h3>
<button type="button" id="btn-add-hw-log" class="btn btn-outline btn-sm" style="height: 30px; font-size: 11px;">이력 추가</button>
<div class="history-header">
<h3>자산 변동 이력</h3>
<button type="button" id="btn-add-hw-log" class="btn btn-outline btn-sm">이력 추가</button>
</div>
<div id="hw-history-list" class="history-timeline"></div>
</div>
</div>
</div>
<div class="modal-footer">
<button id="btn-delete-hw-asset" class="btn btn-outline btn-danger" style="height: 42px;">삭제</button>
<button id="btn-delete-hw-asset" class="btn btn-outline btn-danger">삭제</button>
<div class="footer-actions">
<button id="btn-revert-hw-edit" class="btn btn-outline hidden" style="height: 42px;">수정 취소</button>
<button id="btn-cancel-hw-modal" class="btn btn-outline" style="height: 42px;">닫기</button>
<button id="btn-save-hw-asset" class="btn btn-primary" style="height: 42px;">저장</button>
<button id="btn-revert-hw-edit" class="btn btn-outline hidden">수정 취소</button>
<button id="btn-cancel-hw-modal" class="btn btn-outline">닫기</button>
<button id="btn-save-hw-asset" class="btn btn-primary">저장</button>
</div>
</div>
</div>
@@ -395,25 +391,20 @@ class HwAssetModal extends BaseModal {
if (!container) return;
const row = document.createElement('div');
row.style.display = 'flex';
row.style.gap = '8px';
row.style.alignItems = 'center';
row.className = 'volume-row';
const inputStyle = 'height: 38px !important; box-sizing: border-box !important; font-size: 13px; margin: 0; padding: 0 8px;';
row.innerHTML = `
<select class="vol-type" style="${inputStyle} width: 80px;" ${!this.isEditMode ? 'disabled' : ''}>
<select class="vol-type" ${!this.isEditMode ? 'disabled' : ''}>
<option value="SSD" ${vol.type === 'SSD' ? 'selected' : ''}>SSD</option>
<option value="HDD" ${vol.type === 'HDD' ? 'selected' : ''}>HDD</option>
<option value="NVMe" ${vol.type === 'NVMe' ? 'selected' : ''}>NVMe</option>
</select>
<input type="number" class="vol-cap" value="${vol.capacity || ''}" placeholder="용량" style="${inputStyle} flex: 1;" ${!this.isEditMode ? 'readonly' : ''} />
<select class="vol-unit" style="${inputStyle} width: 70px;" ${!this.isEditMode ? 'disabled' : ''}>
<input type="number" class="vol-cap" value="${vol.capacity || ''}" placeholder="용량" ${!this.isEditMode ? 'readonly' : ''} />
<select class="vol-unit" ${!this.isEditMode ? 'disabled' : ''}>
<option value="GB" ${vol.unit === 'GB' ? 'selected' : ''}>GB</option>
<option value="TB" ${vol.unit === 'TB' ? 'selected' : ''}>TB</option>
</select>
<button type="button" class="btn btn-outline btn-remove-vol edit-only-btn" style="height: 38px !important; padding: 0 12px; color: #E11D48; border-color: #E11D48; display: ${this.isEditMode ? 'inline-flex' : 'none'};">&times;</button>
<button type="button" class="btn btn-outline btn-remove-vol edit-only-btn" style="display: ${this.isEditMode ? 'inline-flex' : 'none'};">&times;</button>
`;
row.querySelector('.btn-remove-vol')?.addEventListener('click', () => row.remove());
@@ -456,7 +447,8 @@ class HwAssetModal extends BaseModal {
// Second Line: Tool & Credentials (Only for IP)
const line2 = document.createElement('div');
line2.className = 'ri-line ri-cred-line';
line2.style.display = info.type === 'IP' ? 'flex' : 'none';
if (info.type !== 'IP') line2.classList.add('hidden');
line2.innerHTML = `
<div class="ri-connector"></div>
<select class="ri-tool" ${!this.isEditMode ? 'disabled' : ''}>
@@ -466,7 +458,7 @@ class HwAssetModal extends BaseModal {
</select>
<input type="text" class="ri-id" value="${parsedId}" placeholder="원격 ID" ${!this.isEditMode ? 'readonly' : ''} />
<input type="text" class="ri-pw" value="${parsedPw}" placeholder="원격 PW" ${!this.isEditMode ? 'readonly' : ''} />
<div class="ri-spacer"></div> <!-- Spacer for the remove button width -->
<div class="ri-spacer"></div>
`;
row.appendChild(line1);
@@ -476,7 +468,7 @@ class HwAssetModal extends BaseModal {
const typeSelect = row.querySelector('.ri-type') as HTMLSelectElement;
typeSelect.addEventListener('change', (e) => {
const isIP = (e.target as HTMLSelectElement).value === 'IP';
line2.style.display = isIP ? 'flex' : 'none';
line2.classList.toggle('hidden', !isIP);
if (!isIP) {
(row.querySelector('.ri-id') as HTMLInputElement).value = '';
(row.querySelector('.ri-pw') as HTMLInputElement).value = '';
@@ -741,9 +733,9 @@ class HwAssetModal extends BaseModal {
private renderHistory(assetId: string) {
const container = document.getElementById('hw-history-list');
if (!container) return;
const logs = (state.masterData.logs || []).filter(l => l.asset_id === assetId);
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.log_date}</div><div class=\"history-user\">${l.log_user}</div><div class=\"history-details\">${l.details}</div></div>`).join('');
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('');
}
private getCategoryKey(asset: any): string {

View File

@@ -100,12 +100,12 @@ class SwAssetModal extends BaseModal {
<div class="form-section-title">관리 및 비고</div>
<div class="form-group sw-standard-field">
<label>${ASSET_SCHEMA.PURCHASE_DATE.ui}</label>
<div style="display:flex; gap:0.25rem; align-items:center; position:relative;">
<input type="text" id="sw-구매일" name="purchase_date" style="flex:1;" />
<button type="button" class="btn-icon" onclick="const p = document.getElementById('sw-구매일-picker'); p.value = document.getElementById('sw-구매일').value; p.showPicker();" style="padding:0.25rem;">
<i data-lucide="calendar" style="width:18px; height:18px; color:var(--primary-color);"></i>
<div class="input-with-btn">
<input type="text" id="sw-구매일" name="purchase_date" />
<button type="button" class="btn-icon" onclick="const p = document.getElementById('sw-구매일-picker'); p.value = document.getElementById('sw-구매일').value; p.showPicker();">
<i data-lucide="calendar"></i>
</button>
<input type="date" id="sw-구매일-picker" style="position:absolute; width:0; height:0; opacity:0; pointer-events:none;" onchange="document.getElementById('sw-구매일').value = this.value" tabindex="-1" />
<input type="date" id="sw-구매일-picker" class="hidden-picker" onchange="document.getElementById('sw-구매일').value = this.value" tabindex="-1" />
</div>
</div>
<div class="form-group sw-standard-field">
@@ -126,12 +126,12 @@ class SwAssetModal extends BaseModal {
</div>
<div class="form-group sw-standard-field" id="sw-expiry-group">
<label>${ASSET_SCHEMA.EXPIRED_DATE.ui}</label>
<div style="display:flex; gap:0.25rem; align-items:center; position:relative;">
<input type="text" id="sw-만료일" name="expiry_date" style="flex:1;" />
<button type="button" class="btn-icon" onclick="const p = document.getElementById('sw-만료일-picker'); p.value = document.getElementById('sw-만료일').value; p.showPicker();" style="padding:0.25rem;">
<i data-lucide="calendar" style="width:18px; height:18px; color:var(--primary-color);"></i>
<div class="input-with-btn">
<input type="text" id="sw-만료일" name="expiry_date" />
<button type="button" class="btn-icon" onclick="const p = document.getElementById('sw-만료일-picker'); p.value = document.getElementById('sw-만료일').value; p.showPicker();">
<i data-lucide="calendar"></i>
</button>
<input type="date" id="sw-만료일-picker" style="position:absolute; width:0; height:0; opacity:0; pointer-events:none;" onchange="document.getElementById('sw-만료일').value = this.value" tabindex="-1" />
<input type="date" id="sw-만료일-picker" class="hidden-picker" onchange="document.getElementById('sw-만료일').value = this.value" tabindex="-1" />
</div>
</div>
<div class="form-group full-width">
@@ -140,18 +140,18 @@ class SwAssetModal extends BaseModal {
</div>
</form>
<div id="sw-user-section" class="user-management-section" style="margin-top: 2rem; border-top: 1px solid var(--border-color); padding-top: 1.5rem;">
<div id="sw-user-section" class="user-management-section">
<button type="button" id="btn-open-sw-user" class="btn btn-outline btn-sm" title="사용자 관리">
<i data-lucide="users" style="width:16px; height:16px; margin-right:4px;"></i> 사용자 관리
<i data-lucide="users"></i> 사용자 관리
</button>
</div>
</div>
<div class="modal-history-area">
<div class="history-header" style="display:flex; justify-content:space-between; align-items:center;">
<h3><i data-lucide="history" style="width:16px; height:16px;"></i> 업데이트 내역</h3>
<div class="history-header">
<h3><i data-lucide="history"></i> 업데이트 내역</h3>
<button type="button" id="btn-open-sw-update" class="btn btn-outline btn-sm">
계약 업데이트 <i data-lucide="refresh-ccw" style="width:14px; height:14px;"></i>
계약 업데이트 <i data-lucide="refresh-ccw"></i>
</button>
</div>
<div id="sw-history-list" class="history-timeline"></div>
@@ -173,7 +173,7 @@ class SwAssetModal extends BaseModal {
<div id="sw-update-modal" class="modal-overlay hidden" style="z-index: 1100;">
<div class="modal-content" style="max-width: 500px;">
<div class="modal-header">
<h2>계약 업데이트 반영</h2>
<h2 class="modal-title">계약 업데이트 반영</h2>
<button id="btn-close-sw-update" class="btn-icon"><i data-lucide="x"></i></button>
</div>
<div class="modal-body">
@@ -184,10 +184,10 @@ class SwAssetModal extends BaseModal {
</div>
<div class="form-group sub-sw-update">
<label>새로운 계약 기간</label>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<input type="text" id="sw-update-start" placeholder="YYYY-MM-DD" style="flex: 1;" />
<div class="input-with-btn">
<input type="text" id="sw-update-start" placeholder="YYYY-MM-DD" />
<span>~</span>
<input type="text" id="sw-update-end" placeholder="YYYY-MM-DD" style="flex: 1;" />
<input type="text" id="sw-update-end" placeholder="YYYY-MM-DD" />
</div>
</div>
<div class="form-group">

View File

@@ -78,12 +78,8 @@ export function renderNavigation(onTabChange: (tab: string) => void) {
adminGroup.className = 'nav-group';
const adminTrigger = document.createElement('div');
adminTrigger.className = 'gnb-trigger';
adminTrigger.className = 'gnb-trigger admin-trigger';
adminTrigger.innerHTML = '관리자';
adminTrigger.style.color = 'var(--text-muted)';
adminTrigger.style.borderLeft = '1px solid var(--border-color)';
adminTrigger.style.marginLeft = '1rem';
adminTrigger.style.paddingLeft = '1.5rem';
adminTrigger.addEventListener('click', () => {
window.open('/map_editor.html', '_blank');