style: UI 가독성 개선 및 LocationView 타입 오류 수정

1. common.css의 --mute 변수 색상 대비값 강화 (#71717a) 및 누락된 자산 상태/성능 등급 배지 CSS 클래스 정의
2. ListFactory.ts에서 테이블 헤더(th) 정렬을 데이터 셀(td)과 일치시키고 장문 생략 시 툴팁(title) 추가
3. common.css에서 타이포그래피 스케일 계산식을 clamp에서 max로 변경하여 상한선 제한 해제 (와이드 화면 대응)
4. LocationView.ts 내 HardwareAsset 타입에 정의되지 않은 asset_purpose를 any로 타입 캐스팅하여 TS2339 빌드 에러 해결
5. 프로젝트 폴더 내 일회성 점검/이관 스크립트 및 Playwright 임시 캡처 로그/이미지 파일 정리
This commit is contained in:
2026-06-19 13:18:55 +09:00
parent c0ef52deac
commit e128634e05
184 changed files with 33 additions and 12666 deletions

View File

@@ -3,7 +3,7 @@
--primary: #171717;
--on-primary: #ffffff;
--body: #4d4d4d;
--mute: #888888;
--mute: #71717a;
--hairline: #ebebeb;
--hairline-strong: #a1a1a1;
--canvas: #ffffff;
@@ -31,13 +31,13 @@
--success: #0070f3;
--header-height: 64px;
/* --- Global Typography Scale (Tighter Clamps) --- */
--fs-xs: clamp(10px, 1vmin + 0.1vw, 13px);
--fs-sm: clamp(12px, 1.2vmin + 0.2vw, 15px);
--fs-base: clamp(13px, 1.4vmin + 0.2vw, 16px);
--fs-md: clamp(16px, 2vmin + 0.3vw, 24px);
--fs-lg: clamp(20px, 3vmin + 0.4vw, 32px);
--fs-xl: clamp(28px, 5vmin + 0.6vw, 48px);
/* --- Global Typography Scale (No Upper Limit) --- */
--fs-xs: max(10px, 1vmin + 0.1vw);
--fs-sm: max(12px, 1.2vmin + 0.2vw);
--fs-base: max(13px, 1.4vmin + 0.2vw);
--fs-md: max(16px, 2vmin + 0.3vw);
--fs-lg: max(20px, 3vmin + 0.4vw);
--fs-xl: max(28px, 5vmin + 0.6vw);
/* --- Layout Units --- */
--header-height: 64px;
@@ -296,6 +296,13 @@ input:checked + .role-slider:before {
font-weight: 600;
}
.badge-primary { background-color: var(--primary); color: var(--on-primary); }
.badge.b-green { background-color: #e6f4ea; color: #137333; } /* 운영/중급 */
.badge.b-yellow { background-color: #fffbeb; color: #b45309; } /* 재고/보급 */
.badge.b-purple { background-color: #f3e8ff; color: #6b21a8; } /* 수리/최상급 */
.badge.b-primary { background-color: #e0e7ff; color: #3730a3; } /* GNB/상급 */
.badge.badge-danger { background-color: #fce8e6; color: #c5221f; } /* 폐기/교체대상 */
.badge.badge-muted { background-color: #f1f3f4; color: #5f6368; } /* 폐기 */
.badge.badge-light { background-color: var(--canvas-soft-2); color: var(--mute); border: 1px solid var(--hairline); } /* 재고기본 */
/* --- Form Elements Extra --- */
.input-with-icon {

View File

@@ -744,14 +744,21 @@ export function createListView(container: HTMLElement, config: ListViewConfig) {
let filtered = applyCommonFilters(fullList, currentFilters, config.searchKeys as any[]);
if (sortState.key) filtered = dynamicSort(filtered, sortState.key, sortState.direction);
thead.innerHTML = `<tr>${config.columns.map(col => `<th ${col.sortKey ? `data-sort="${col.sortKey}"` : ''} style="${col.width ? `width:${col.width};` : ''}">${col.header}</th>`).join('')}</tr>`;
thead.innerHTML = `<tr>${config.columns.map(col => {
const isDateCol = col.header.includes('일') || col.header.includes('날짜') || col.header.includes('연월');
const alignmentClass = col.align ? `text-${col.align}` : (isDateCol ? 'text-center' : '');
return `<th class="${alignmentClass}" ${col.sortKey ? `data-sort="${col.sortKey}"` : ''} style="${col.width ? `width:${col.width};` : ''}">${col.header}</th>`;
}).join('')}</tr>`;
tbody.innerHTML = filtered.length === 0 ? `<tr><td colspan="${config.columns.length}" class="text-center empty-cell">${UI_TEXT.MESSAGES.NO_DATA}</td></tr>`
: filtered.map(asset => `<tr class="asset-row clickable" data-id="${asset.id}">${config.columns.map(col => {
const isDateCol = col.header.includes('일') || col.header.includes('날짜') || col.header.includes('연월');
const alignmentClass = col.align ? `text-${col.align}` : (isDateCol ? 'text-center' : '');
const customClass = col.className || '';
return `<td class="${alignmentClass} ${customClass}" style="${col.width ? `width:${col.width};` : ''}">${col.render(asset)}</td>`;
const rendered = col.render(asset);
const rawText = rendered.replace(/<[^>]*>/g, '').trim();
const titleAttr = rawText && rawText !== '-' ? `title="${rawText.replace(/"/g, '&quot;')}"` : '';
return `<td class="${alignmentClass} ${customClass}" style="${col.width ? `width:${col.width};` : ''}" ${titleAttr}>${rendered}</td>`;
}).join('')}</tr>`).join('');
tbody.querySelectorAll('.asset-row').forEach((tr, idx) => { tr.addEventListener('click', () => config.onRowClick && config.onRowClick(filtered[idx])); });

View File

@@ -87,7 +87,7 @@ export async function renderLocationView(container: HTMLElement) {
<div id="box-overlay" class="map-overlay">
${boxes.map((box: any, idx: number) => {
const asset = allHwAssets.find(a => a.id === box.asset_id);
const name = asset ? (asset.asset_purpose || asset.asset_code) : (box.name || `#${idx+1}`);
const name = asset ? ((asset as any).asset_purpose || asset.asset_code) : (box.name || `#${idx+1}`);
// w, h가 없거나 너무 작으면 최소 크기(3%) 보장하여 영역으로 표시
const width = Math.max(parseFloat(box.w || '3'), 3);
const height = Math.max(parseFloat(box.h || '3'), 3);