# 대시보드 다크 UI 전면 개편 구현 계획 날짜: 2026-07-16 목업: `review/ui_mockup_v2.html` (사용자 승인 완료) 브랜치: feat/pi-c-sensor3-leak-node (또는 신규 feat/dashboard-dark-ui) ## 배경·목표 목업(다크 관제 테마, 글래스 툴바, 결합 센서 카드, 카드형 테이블)을 실제 `php/dashboard.php` + `php/assets/app.css` + `php/tabs/*.php` 에 반영한다. 폐쇄망 제약 유지: 외부 CDN/폰트/JS 0, 차트는 서버 렌더 인라인 SVG. ## 센서 토폴로지 (표현의 핵심) | id | 구성 | 보고 주기 | 특징 | |----|------|-----------|------| | 1 | 누수 + 온습도 결합 (Pi-A) | 10분 | 누수 사진 촬영·업로드 | | 2 | 온습도 단독 (Pi-B) | 1시간 | 오프라인 판정 임계 김(≈125분) | | 3 | 누수 + 온습도 결합 (Pi-C) | 10분 | 누수 사진 촬영·업로드 | ### 발견된 기존 UX 결함 (이번 개편에서 반드시 해결) `tabs/live.php` 는 id 중복 시 metric 카드가 leak 카드를 가린다 (`if (!isset($sensor_cards[$sid]))`). → 1·3번 센서의 **누수 상태가 실시간 화면에 표시되지 않는다.** 결합 카드로 통합해 해결한다. ## 카드 설계 (센서 특징별) ### A. 결합 카드 (id 1·3) — 한 장에 두 계통 - 헤더: 센서명 + 칩 2개 `누수` `온습도` (또는 단일 칩 `누수+온습도`) - 상태 라인 우선순위: 오프라인 > 누수(확정) > 확인중(디바운스) > 온습도 경보 > 정상 - 누수와 온습도 경보 동시면: 상태 라인은 누수, 온습도 칩에 경보색 유지 - 본문 2행: 1. 누수 행: 상태 점 + 텍스트. 누수 중이면 경과 시간·SMS 발송 수·**최근 사진 썸네일**(photo.php 링크) 2. 온습도 행: 온도/습도 큰 숫자 + 24h 스파크라인 + 예보 칩(여유/접근) - 누수 중 시각 효과: 카드 glow 펄스 + 하단 물결 SVG (reduced-motion 시 정지) - 푸터: 최종확인 시각 · `10분 주기` 표기 ### B. 온습도 단독 카드 (id 2) - 결합 카드에서 누수 행 제거한 형태. `1시간 주기` 표기. - 오프라인 elapsed 표기는 기존 로직 유지. ### C. 데이터 없음/오프라인 placeholder — 기존 로직 유지, 새 스타일만. ## 구현 페이즈 ### Phase 1 — 디자인 토큰·셸 (dash-dark.css 신설 + dashboard.php) 0. 확인 완료: app.css 는 login/monthly_report/setup_wizard 등 7개 페이지 공용 → 직접 교체 금지. **`assets/dash-dark.css` 신설**, dashboard.php 만 app.css 뒤에 추가 로드해 토큰·컴포넌트를 오버라이드. 타 페이지 무변경. 1. `dash-dark.css` 토큰: 다크 팔레트(--bg/--surface/--ink/--ok/--warn/--err/--leak/--temp/--hum), spring easing 변수, 라운드/간격 토큰. 기존 클래스명 유지(마크업 변경 최소화). 2. 글래스 툴바(sticky + backdrop-filter), 새로고침 카운트다운 링(기존 30초 리로드 JS 그대로, 표시만 교체). 3. 히어로/알림 스트립/KPI 스트립/세그먼트 탭바 스타일 교체. 4. `prefers-reduced-motion`, `prefers-reduced-transparency` 블록. 5. 인쇄(tab=all) 대비: `@media print` 에서 다크 배경 → 흰 배경·검정 잉크로 강제 (기존 인쇄·보안 증적 워크플로 보존). monthly_report*·login 등 타 페이지는 건드리지 않음. ### Phase 2 — live 탭: 결합 센서 카드 1. `tabs/live.php` 카드 병합 로직 재작성: id별로 metric+leak 상태 모두 보유하는 구조(`['metric' => s|null, 'leak' => s|null]`)로 변경. 2. 결합/단독/누수단독 3분기 렌더. 상태 우선순위 규칙 위 설계대로. 3. 누수 중 카드에 최근 사진 썸네일: `load_tab_live()` 에서 미복구 사고의 최신 photo id 1~2건 조회 추가 (`leak_photos` 테이블, 기존 history 쿼리 재사용). 4. 24h 스파크라인: `load_tab_live()` 에 센서별 최근 24h 측정 다운샘플(≤48pt) 쿼리 추가, 인라인 SVG polyline 서버 렌더(트렌드 차트 헬퍼 축소판). 5. 보고 주기 표기: 설정 상수에서 도출(하드코딩 금지). ### Phase 3 — trend 탭 스타일 이식 1. 기존 SVG 차트 구조 유지(임계선·피크 플래그 이미 있음), 클래스 → 새 토큰 매핑. 2. 통계 위젯(7일 추이/도넛/게이지/리더보드) 카드 스타일 교체. 마크업 거의 그대로. ### Phase 4 — history 탭 카드형 테이블 1. 테이블 4종을 `tablecard`(헤더+건수 필) 래핑, 행 hover·경보 행 강조. 2. 사진 썸네일 hover 확대. details 접힘(모바일) 동작 유지. 3. 30일 평균·SMS 통계 그리드 새 스타일. ### Phase 5 — system 탭 + 마무리 1. system 탭 진단 목록 새 스타일(구조 변경 없음). 2. `tests/` PHP 테스트 통과 확인(헬퍼 시그니처 불변이므로 영향 최소 예상). 3. 반응형(모바일 768px) + 인쇄(tab=all) 실기 확인. 4. `deploy/01_server_cafe24` 에 app.css·tabs 복사본 있으면 동기화 확인. ## 지키는 것 (불변) - 서버 렌더 구조·URL 스킴(?tab=, ?range=)·30초 리로드·details 복원 JS - 임계 판정/SMS 로직 (표시 전용 개편) - WCAG: 새로고침 일시정지 버튼, aria-current, 명도 대비(다크에서 4.5:1 재검증) - 폐쇄망: 외부 리소스 0 ## 리스크 - 다크 배경 인쇄: tab=all 인쇄 증적이 검정 배경으로 나가면 안 됨 → Phase 1 의 @media print 강제 라이트가 방어. 실기 인쇄 미리보기 확인 필수. - app.css 651줄 전면 교체 → 페이지별(login, setup_wizard 등) 공용 여부 확인 후 dashboard 전용 분리 또는 공용 토큰만 교체 결정 (Phase 1 착수 시 grep).