feat(ui/ux): unify typography to Pretendard and enforce read-only view mode as default

- Set global font-family to Pretendard and letter-spacing to -0.02em.
- Standardized table header font-size to var(--fs-sm).
- Fixed table clipping and sticky header behavior at 1920x1080.
- Implemented dynamic select options in search filters.
- Enforced 'view' mode as default for all asset modals (PC, Server, SW, etc.).
- Improved Modal logic to ensure all fields (including dynamic rows) are correctly locked.
- Updated Location View detail button from 'Edit' to 'View'.
- Updated design_rule.md to reflect new typography standards.
This commit is contained in:
2026-06-18 11:13:16 +09:00
parent 2cb4b87c0a
commit 3db05f2939
14 changed files with 143 additions and 99 deletions

View File

@@ -18,6 +18,7 @@ export interface FilterOptions {
extraHTML?: string;
onFilterChange: (filters: any) => void;
initialFilters?: any;
fullList?: any[]; // For populating dynamic filters
}
/**
@@ -38,11 +39,18 @@ export function renderFilterBar(container: HTMLElement, options: FilterOptions)
showStatus = false,
extraHTML = '',
onFilterChange,
initialFilters = { keyword: '', corp: '', dept: '', loc: '', field: '', type: '', status: '' }
initialFilters = { keyword: '', corp: '', dept: '', loc: '', field: '', type: '', status: '' },
fullList = []
} = options;
container.classList.add('search-bar'); // Restored class
// Helper to get unique sorted values
const getUnique = (key: keyof typeof ASSET_SCHEMA | string) => {
const fieldKey = (ASSET_SCHEMA as any)[key]?.key || key;
return Array.from(new Set(fullList.map(item => item[fieldKey] || item[(ASSET_SCHEMA as any)[key]?.db]).filter(Boolean))).sort();
};
container.innerHTML = `
<div class="search-item flex-1">
<label>${keywordLabel}</label>
@@ -53,6 +61,7 @@ export function renderFilterBar(container: HTMLElement, options: FilterOptions)
<label>${ASSET_SCHEMA.ASSET_TYPE.ui}</label>
<select id="filter-type">
<option value="">전체 유형</option>
${getUnique('ASSET_TYPE').map(v => `<option value="${v}" ${initialFilters.type === v ? 'selected' : ''}>${v}</option>`).join('')}
</select>
</div>` : ''}
${showStatus ? `
@@ -60,6 +69,7 @@ export function renderFilterBar(container: HTMLElement, options: FilterOptions)
<label>${ASSET_SCHEMA.HW_STATUS.ui}</label>
<select id="filter-status">
<option value="">전체 상태</option>
${getUnique('HW_STATUS').map(v => `<option value="${v}" ${initialFilters.status === v ? 'selected' : ''}>${v}</option>`).join('')}
</select>
</div>` : ''}
${showField ? `
@@ -81,12 +91,18 @@ export function renderFilterBar(container: HTMLElement, options: FilterOptions)
${showLoc ? `
<div class="search-item">
<label>${ASSET_SCHEMA.LOCATION.ui}</label>
<select id="filter-loc"><option value="">전체 위치</option></select>
<select id="filter-loc">
<option value="">전체 위치</option>
${getUnique('LOCATION').map(v => `<option value="${v}" ${initialFilters.loc === v ? 'selected' : ''}>${v}</option>`).join('')}
</select>
</div>` : ''}
${showDept ? `
<div class="search-item">
<label>${ASSET_SCHEMA.CURRENT_DEPT.ui}</label>
<select id="filter-dept"><option value="">전체 조직</option></select>
<select id="filter-dept">
<option value="">전체 조직</option>
${getUnique('CURRENT_DEPT').map(v => `<option value="${v}" ${initialFilters.dept === v ? 'selected' : ''}>${v}</option>`).join('')}
</select>
</div>` : ''}
${extraHTML}
<button id="btn-reset-filters" class="btn btn-outline btn-reset">