diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md
index 67d75ec..d04e117 100644
--- a/docs/BACKLOG.md
+++ b/docs/BACKLOG.md
@@ -16,3 +16,14 @@
| B-10 | Minor | 홀매니저(SCR-10/11)·현장 모바일(SCR-M1/M2) 화면에 Phase 2/3 라벨 부착, 조명 배치안 제안(M4a) 전용 UI 검토 | designer | open |
| B-11 | Major | ReRoomAI 소스 분석(docs/analysis/reroomai-source.md) — 소스 폴더 연결 대기 중. 완료 후 PLANNING §6 ReRoomAI 연계 절 보강 | planner/visualizer | **done** (v1.1) — 소스 분석 완료·PLANNING §6-4/6-5 확정(모델·SDK·구조화 사전·보존/교체 프롬프트 템플릿·RenderJob 방어·UX), §10 R11 해소·R12 추가 |
| B-12 | Minor | client.py에 동일 시드/일관성 파라미터(PLANNING §6-3) 지원 검토 (Gemini API 시드 지원 범위 확인 필요) | visualizer | **done** (v1.2) — `render_shot(..., seed=)` 지원. `GenerateContentConfig(seed=)`로 전달 시도하되 SDK/모델 미지원(TypeError)이면 자동으로 참조체인 기반 일관성(첫 컷을 다음 샷 reference_image로 재사용)으로 폴백. SKILL.md에 명시. ★실호출 검증은 소유자 승인 후 |
+
+## 신규 5화면(SCR-13~17) reviewer 검증 티켓 (2026-07-11 · 배포 가능 판정, 전부 Minor)
+
+| ID | 심각도 | 내용 | 담당 | 상태 |
+|---|---|---|---|---|
+| R13-01 | Minor | SCR-13 추세 차트 "AI 예측 점선 구간"이 스펙·힌트 문구엔 있으나 AreaChart가 점선 예측 구간을 미렌더 — 힌트가 없는 요소를 지칭(오도 소지). 점선 렌더 구현 또는 힌트 정정 | developer(designer 확인) | open |
+| R15-01 | Minor | SCR-15 홀 셀렉트가 필터 로직에 미배선(선택 무효과) | developer | **done** (2026-07-11) — `matchesHall()` 배선("홀" 뒤 번호만 파싱, "제N전시장" N 오매칭 방지), tsc 재통과 |
+| R15-02 | Minor | SCR-15 실 워크스페이스 모드에서 category를 'exhibition' 하드코딩 — 샘플/기본값 시각 표기 없음(estVisitors는 "집계 대기" 표기됨) | developer | open |
+| R17-01 | Minor | SCR-17 스타일가이드에 "시스템 아이콘 라이브러리" 섹션 누락(스펙 9항목 중 1) — 아이콘 세트 교체(UNDEVELOPED_BACKLOG §1)와 함께 처리 권장 | developer(designer) | open |
+| R17-02 | Minor | `chartColors.ts`의 `CHART.warning` 키가 §1-2 warning(#B45309)이 아닌 §1-4 violation-warn(#F79009) 값 — 값은 토큰 정합, 키 이름만 오용 위험 → `violationWarn` 등으로 개명 권장 | developer | open |
+| R00-01 | 정보 | AppShell 단일 셸에 전 역할 네비 무차별 노출 — 역할별 포털+MDI 분리는 미착수 대형 트랙으로 기추적(UNDEVELOPED_BACKLOG §1·§4) | FE·DES | tracked |
diff --git a/docs/UNDEVELOPED_BACKLOG.md b/docs/UNDEVELOPED_BACKLOG.md
new file mode 100644
index 0000000..babbd92
--- /dev/null
+++ b/docs/UNDEVELOPED_BACKLOG.md
@@ -0,0 +1,79 @@
+# 미개발 백로그 — 세션 스캔 통합 (UNDEVELOPED_BACKLOG)
+
+> 2026-07-11 세션 대화 전체 스캔 결과. "무엇이 아직 개발 안 됐는가"를 단일 문서로 통합.
+> 상위 문서: `WORK_STATUS.md`(인수인계) · `IMPLEMENTATION_BACKLOG.md`(Phase 구조) · `FEATURE_BACKLOG_100.md`(100대 기능) · `BACKLOG.md`(reviewer 티켓).
+> 상태: ⬜ 미착수 · 🔶 부분(샘플/스텁) · 🔷 진행 중 · ⏸ 게이트 대기
+
+---
+
+## 1. 신규 5화면(SCR-13~17) 트랙 — 이번 세션 파생
+
+구현 자체는 완료(프론트 16파일 생성·tsc 통과, QA 진행 중). 아래는 **화면은 있으나 데이터/백엔드가 미개발**인 잔여.
+
+| 상태 | 항목 | 내용 | 담당 | 편입 Phase |
+|---|---|---|---|---|
+| 🔶 | SCR-13 BI 실데이터 전환 | BI 데이터마트·KpiSnapshot 파이프라인 미구축 → 화면 전체 샘플. 집계 API(매출·RevPAD·P&L·리텐션·예측) 신설 필요 | DA·BI·BE | D-M16 |
+| 🔶 | SCR-14 현장운영 실전환 | 혼잡=M10 체크인 파생, 전력=M4 부하 집계로 실전환 경로 확보. CCTV·HVAC/전력계·iparking·조명 IoT는 **하드웨어 계약 필요 — 연동 코드 착수 금지** | BE·FE | E-M14 |
+| 🔶 | SCR-15 일정 실전환 | 행사 목록만 실(인증 workspaces). WorkspaceDto에 category·estVisitors 필드 추가 + 홀 가동률 집계 API + 캘린더 점유 실데이터 | BE·FE | D-M1/6 |
+| 🔶 | SCR-16 관리자 집계 실전환 | 사용자수·활성행사수 등 실 가능 지표 API 연결. 실시간 방문객·주차·라이브는 M10/M14 이후 | ADM·BE | D-M18 |
+| ⬜ | M18 관리자 본체 화면 | `/admin/{users,roles,codes,menus,audit,settings,masterdata/*}` 7종 — 랜딩(SCR-16)만 존재, 본체 CRUD 화면 미구현 (백엔드 B-2 시스템관리 API는 라이브) | ADM·FE | D-M18 |
+| ⬜ | SCR-16 플로팅 AI 봇 | design.md상 P2·비노출 기본 — 미구현(주석만) | AI·FE | P2 |
+| ⬜ | AppShell 기존 네비 배선 | 대시보드·플로어플랜·참가업체·서류·정산 5항목 여전히 `href="#"` — 행사 스코프 라우트라 워크스페이스 컨텍스트 선택 UX 필요(신규 4항목만 배선됨) | FE·DES | C-C |
+| ⬜ | `/_styleguide` 노출 방침 | 내부 전용 라우트로만 구분 — 프로덕션 빌드 제외(env 분기 등) 방침 미확정 | FE·TA | E-DEP |
+| ⬜ | Stitch 아이콘 세트 교체 | 이모지/글리프 → `stitch_kintex_ai_system_architect/_icons/` 정식 아이콘 전면 교체 | FE·DES | C-C |
+| ⬜ | Stitch 구버전 폴더 정리 | `component_guide_kintex_ai_system/`(구버전, updated로 대체됨) 정리 — **삭제는 사용자 확인 후** | — | — |
+
+## 2. 백그라운드 산출물 — 커밋 대기·미완 검증 필요
+
+| 상태 | 항목 | 내용 | 비고 |
+|---|---|---|---|
+| 🔷 | 모바일 앱(Expo) `mobile/` | 스캐폴드 생성됨 — 미커밋. 빌드/실행 검증·기능 범위 확정 미완 | node_modules gitignore 확인 |
+| 🔶 | 산출물 `docs/deliverables/` | 사업수행계획서.docx + `_gen/` 스크립트만 확인됨. **지침서 3종(사용자·운영자·개발자) PPT·프로그램 사양서+순서도 PPT 폴더 부재 → 재실행 필요**. 자동갱신 스크립트 검증 미완 | `gen_xlsx.py.tmp.*` 잔재 정리 |
+| ⬜ | 잡파일 정리 | `hs_err_pid*.log`·`replay_pid*.log`(JVM 크래시 잔재)·`_gen/*.tmp.*` — 삭제는 사용자 확인 후 | 루트 오염 |
+| ⬜ | `ci/`(CI 로고 자산) 커밋 여부 | 미추적 상태 — 번들 참조 여부 확인 후 커밋/ignore 결정 | |
+
+## 3. 전 화면 공통 NFR — 미적용 (WORK_STATUS §6 이월)
+
+| 상태 | 항목 | 내용 |
+|---|---|---|
+| 🔶 | 라이트/다크 테마 | 토큰 변수는 준비 — 전 화면 다크 검증·토글 UI 미구현 |
+| ⬜ | 다국어(i18n) | 한/영/중/일 — i18n 프레임워크 자체 미도입(문구 하드코딩) |
+| 🔶 | 웹접근성 | 신규 화면은 aria/role 반영 — 기존 화면 전면 감사·WCAG AA 준수 검증 미완 |
+| 🔶 | 반응형 풀스크린 | 데스크톱 1440 기준 — 태블릿/모바일 브레이크포인트 전면 적용 미완 |
+| ⬜ | 시큐어코딩 점검 | 전면 감사(입력 검증·XSS·CSRF) 미실행 |
+
+## 4. 아키텍처·플랫폼 대형 트랙 — 미착수
+
+| 상태 | 항목 | 내용 | 편입 |
+|---|---|---|---|
+| ⬜ | 멀티테넌시 구현 | PLANNING v3.0 기획만 완료 — DA 데이터모델 → tenant_id 스키마 → 백엔드 테넌트 컨텍스트 → 프론트 테넌트 스위치 | DA·DB·BE |
+| ⬜ | MDI 셸 전환 | design.md §2.7 다중문서 인터페이스 — 현 AppShell은 단일 문서 | FE·DES |
+| ⬜ | 100대 기능 갭 | FEATURE_BACKLOG_100 기준 신규 19 + 부분 18 — 관람객·네트워킹·참가업체 서비스 집중, orchestrator Phase 편입 필요 | 전체 |
+
+## 5. 도메인 모듈(Phase D/E) — 미착수
+
+| 상태 | 모듈 | 내용 |
+|---|---|---|
+| ⬜ | M15 공사/장치 옥션 | AI자료 열람→견적서 제출→역경매→낙찰·계약. 등록업체만 응찰 |
+| ⬜ | M10 관람객·현장 | 등록·티켓(PG)·배지/QR·체크인·리드캡처 — SCR-14/16 실데이터의 선행 |
+| ⬜ | M12/M17 CMS·공개사이트 | 헤드리스 CMS·마이크로사이트·일반 대중 공개 홍보 사이트(SEO·다국어) |
+| ⬜ | M16 BI 백엔드 | 데이터마트·집계·수요예측 — SCR-13 프론트는 완료(샘플) |
+| ⬜ | M18 관리자 본체 | §1 참조 — 마스터데이터(홀·요율·룰셋·등록업체) CRUD 포함 |
+| ⬜ | M1/6/7/9 | 홀 배정·자동견적(요율 룰)·마일스톤/서식·매칭·정산/결제 |
+| ⬜ | M11 비즈매칭 · M13 wayfinding | P2 |
+
+## 6. 잔여 reviewer 티켓 (BACKLOG.md open)
+
+B-01(조립부스 옵션 UI)·B-04(화면 수 표기)·B-05(정산 메뉴 IA)·B-06(이메일 인증 프롬프트)·B-07(SCR-03 공유·핀 불일치)·B-08(SCR-04 산술 오류)·B-10(Phase 라벨·조명 UI) — 전부 designer 담당.
+
+## 7. 게이트·인프라 후속
+
+| 상태 | 항목 | 내용 |
+|---|---|---|
+| ⏸ | 운영 도메인 | `kintex.wise.ai.kr` 전환(현 개발 kintex.zioinfo.co.kr) — 소유자 확정 후 |
+| 🔷 | 이번 트랙 마감 | QA(진행 중) → reviewer 정합 검증 → 커밋·push(자동배포) → WORK_STATUS 갱신 |
+
+## 변경 이력
+| 일자 | 갱신 |
+|---|---|
+| 2026-07-11 | 최초 작성 — 세션 대화 전체 스캔(신규 5화면 파생 잔여·커밋 대기·NFR·대형 트랙·도메인·티켓·게이트) |
diff --git a/docs/WORK_STATUS.md b/docs/WORK_STATUS.md
index 8593ccf..0978480 100644
--- a/docs/WORK_STATUS.md
+++ b/docs/WORK_STATUS.md
@@ -64,7 +64,8 @@
- 프로그램 사양서(기능별 상세) + 순서도 PPT(`docs/deliverables/프로그램사양서/`).
## 6. 남은 큐 (후속)
-- **신규 5화면**: BI(M16)·Hall Operations(M14)·Exhibition Schedule·Admin Dashboard(M18)·Component Guide — Stitch 재취득 완료, 반영 대기.
+> **상세 미개발 통합 목록: `docs/UNDEVELOPED_BACKLOG.md`** (2026-07-11 세션 스캔 — 화면별 샘플→실데이터 전환·커밋 대기·NFR·대형 트랙 전체)
+- **신규 5화면**: ~~반영 대기~~ → **구현 완료(2026-07-11)** — SCR-13~17(경영분석 `/analytics`·현장운영 `/ops/operations`·전시일정 `/schedule`·관리자 랜딩 `/admin`·스타일가이드 `/_styleguide`) design.md v1.3 매핑 + React 이식(tsc 통과·Recharts 도입). QA·reviewer·커밋 마감 진행 중. 데이터는 대부분 샘플(집계 API 미구축 — UNDEVELOPED_BACKLOG §1).
- **아이콘 세트 교체**(이모지 → Stitch 정식 아이콘, `_icons/`).
- **반응형 풀스크린 + 라이트/다크 테마 + 다국어(i18n) + 접근성** 전면 적용.
- **100대 기능 갭**(신규19/부분18) → orchestrator Phase 편입 구현(관람객·네트워킹·참가업체 서비스 집중).
@@ -83,3 +84,4 @@
| 일자 | 갱신 |
|---|---|
| 2026-07-11 | 최초 작성 — 요구사항 27건·현황·남은 큐·함정 |
+| 2026-07-11 | 신규 5화면(SCR-13~17) 구현 완료 반영 + 미개발 통합 백로그 `UNDEVELOPED_BACKLOG.md` 신설·연결 |
diff --git a/docs/design.md b/docs/design.md
index bfe61c3..3a95cf2 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -1,6 +1,6 @@
# 킨텍스 AI 전시관리 시스템 — UI 디자인 스펙 (design.md)
-> 작성: 디자인 에이전트(designer) · 작성일: 2026-07-11 · 버전: v1.2
+> 작성: 디자인 에이전트(designer) · 작성일: 2026-07-11 · 버전: v1.3
> 근거 문서: `docs/PLANNING.md` v1.0 (모듈 맵 M1~M9, P0 기능, 나노바나나 표준 샷 세트 S1~S7) · Stitch 산출물 `stitch_kintex_ai_system_architect/`(18화면 + DESIGN.md 3변형) 학습·정합
> **단일 출처(Single Source of Truth)**: 프론트 구현 토큰·컴포넌트 계약은 본 문서가 권위다. Stitch 화면(code.html/screen.png)은 시각 참조로만 사용하며, 상충 시 본 문서를 따른다.
> 용도: **각 화면의 "Stitch 프롬프트" 코드블록을 Google Stitch(stitch.withgoogle.com)에 그대로 붙여넣어 화면을 생성**한다. 문서는 한국어, Stitch 프롬프트만 영어.
@@ -146,6 +146,22 @@
각 SCR의 상세 레이아웃·상태·Stitch 프롬프트는 아래 §3(웹)·§4(모바일)에 정의돼 있다. Stitch 화면은 시각 참조(screen.png)로만 사용하고, 프론트 토큰·컴포넌트 계약은 본 문서를 따른다.
+### 2.5-1. v2.0 확장 화면 매핑 (SCR-13~17 — 도메인·경영·시스템·스타일가이드)
+
+PLANNING v2.0/v3.0에서 도메인 모듈(M10~M18)이 정식 편입되며, Stitch가 재취득한 아래 5개 화면을 SCR-13~17로 정합화한다. §2.6에서 "P2 후보(기획 미반영)"로 보류됐던 4개 화면 중 **M14·M16·M18은 planner가 PLANNING §5/§5A에 정식 반영**(M16 P1 승격·M18 P1·M14 P2)하여 승격 요건을 충족했고, exhibition_schedule은 방문객용이 아닌 **운영사·주최자용 행사 일정/홀 가동 관리 화면**으로 재해석되어 M1(홀 배정·행사일정)·M6(마일스톤)에 접합된다. SCR-17은 §1 디자인 시스템의 실증 스타일가이드(제품 화면 아님·내부 참조)다.
+
+| Stitch 화면 디렉터리 | SCR ID | 화면명 | 모듈 | 우선순위 | 대상 역할 | 플랫폼 |
+|---|---|---|---|---|---|---|
+| `business_intelligence_kintex_ai_system` | SCR-13 | 경영분석 대시보드 | **M16** | P1 | 주최자·운영사(참가업체 ROI 관점 병행) | 웹 |
+| `hall_operations_kintex_ai_system` | SCR-14 | 홀 현장운영 대시보드 | **M14** | P2 | 홀매니저·운영 | 웹 |
+| `exhibition_schedule_kintex_ai_system` | SCR-15 | 전시 일정 관리 | **M1·M6** | P1 | 주최자·운영사 | 웹 |
+| `admin_dashboard_kintex_ai_system` | SCR-16 | 관리자 대시보드 | **M18** | P1 | 테넌트 관리자·플랫폼 슈퍼관리자 | 웹(백오피스) |
+| `component_guide_updated_kintex_ai_system` | SCR-17 | 컴포넌트 가이드(스타일가이드) | §1 디자인 시스템 | — (내부 참조) | 디자이너·프론트 개발 | 웹(내부) |
+
+> **`component_guide_updated`가 최신본**이며 `component_guide`(구버전)은 참조하지 않는다. SCR-17은 배포 제품 라우트가 아닌 **개발/디자인 내부 참조(스토리북 성격)**로만 노출한다.
+
+> **공통 NFR(SCR-13~17)**: ① **테마** — 라이트 모드 단일이 기본(§1-5), Recharts·게이지·히트맵 등 데이터 시각화는 §1 컬러 토큰을 CSS 변수로 주입해 향후 다크모드(Phase 3) 전환에 대비(하드코딩 hex 금지). ② **웹접근성** — 명도 대비 WCAG AA 이상, 차트는 색 외 패턴/라벨 병기, KPI·표는 `aria-label`·스크린리더 읽기 순서 준수, 키보드 포커스 링 `primary-600` 2px. ③ **다국어** — 화면 문자열은 i18n 키로 분리(M17 CMS 다국어 한/영/중/일 정책 정합), 숫자·통화·날짜는 로케일 포맷(tabular numerals) 사용. ④ **AI 산출물 구분** — 예측·매칭·이상탐지 등 AI 지표는 AiLabel(보라 `ai-accent`)로 사람 산출물과 항상 구분(§1-4).
+
## 2.6 범위 게이트 — P2 후보 (기획 반영 전 이식 금지)
`docs/PLANNING.md`가 **범위 권위**다(부스 신청→설계→유틸리티→규정검증→승인→시공→검수 파이프라인 중심). Stitch `kintex_ai_system_proposal.md`와 아래 4개 Stitch 화면은 PLANNING 범위 밖 비전(AI 컨시어지·CCTV 혼잡도·에너지 최적화·비즈니스 매칭·AR 내비 등)이므로 **P2 후보로만 분류**한다. **P0/P1으로 끌어오지 않으며, 승격하려면 먼저 planner에 기획 반영을 요청해야 한다(designer 임의 승격 금지).**
@@ -159,6 +175,8 @@
> 위 4개 Stitch 화면의 시각 자산은 참고만 하고 프론트 구현에 착수하지 않는다. `kintex_ai_system_proposal.md`는 Stitch가 자동 생성한 확장 비전 문서로, 우리 PLANNING과 별개다.
+> **갱신(v1.3 · 2026-07-11)**: 위 표의 3개 화면은 **planner의 정식 기획 반영으로 P2 후보 게이트를 통과**했다 — `business_intelligence`→**M16 경영분석 BI(P1 승격, PLANNING §5A M16·M16-1)**, `hall_operations`→**M14 현장운영(P2, PLANNING §5A M14)**, `admin_dashboard`→**M18 관리자 시스템(P1, PLANNING §5A M18·§5B)**. 따라서 designer 임의 승격이 아니라 기획 근거를 갖춰 각각 SCR-13·SCR-14·SCR-16으로 정합화한다(§2.5-1·§3). `exhibition_schedule`은 방문객 서비스가 아닌 **운영사·주최자용 행사일정/홀 가동 관리 화면**(M1 배정 가용성 캘린더 + M6 마일스톤)으로 재분류되어 SCR-15로 편입한다. 단, Stitch 화면이 담은 **비전성 요소(CCTV/센서 실시간 혼잡·에너지 IoT·AI 컨시어지 플로팅 봇·매칭 성과 분석 등)는 여전히 해당 모듈의 P2/후속 범위**이며, PLANNING이 명시한 초기 데이터 원천(M4/M10 파생·수기 입력) 밖의 하드웨어 연동은 착수하지 않는다(§3 각 SCR "데이터 원천" 참조).
+
---
## 2.7 MDI 셸 (다중 문서 인터페이스) — AppShell 표준 (v1.2 신설)
@@ -269,7 +287,7 @@ An enterprise MDI (multiple document interface) application shell for "KINTEX AI
## 3. 화면별 스펙
-> P0 모듈(M2·M3·M4·M5) 중심 총 14개 화면(웹 12 + 모바일 2). 각 Stitch 프롬프트는 화면 1개를 1회 생성하는 기준으로 작성했다.
+> P0 모듈(M2·M3·M4·M5) 중심 총 14개 화면(웹 12 + 모바일 2) + **v2.0 확장 SCR-13~17(경영분석 M16·홀운영 M14·전시일정 M1·M6·관리자 M18·컴포넌트 가이드)**. 각 Stitch 프롬프트는 화면 1개를 1회 생성하는 기준으로 작성했다.
---
@@ -477,6 +495,118 @@ An AI-render gallery screen for exhibition booth visualizations in a Korean web
---
+### SCR-13 경영분석 대시보드 (히어로: 매출·가동률 지표 + 추세 차트) [M16 BI]
+
+- **대상**: 주최자·킨텍스 운영사(관점 토글로 참가업체 ROI 병행) · **진입 경로**: 주최자 콘솔/운영 대시보드 사이드바 → "경영분석" (탭 열기)
+- **모듈·우선순위**: M16 경영분석 BI · **P1**(PLANNING §5A M16·M16-1). BI는 두 관점을 격리 제공 — **① 운영사(킨텍스) 관점 수익성/ROI**(기본)와 **② 참가업체 관점 ROI**(리드·매칭·부스 비용 대비 성과). 상단 관점 토글로 전환하며 권한으로 분리(참가업체는 자기 부스 범위만).
+- **레이아웃 (위→아래)**:
+ 1. 헤더: 타이틀 "경영분석" + 부제 "킨텍스 운영 수익성 · 참가업체 인사이트", 우측 관점 토글([운영사] / [참가업체]), 기간 셀렉트("이번 행사 / 최근 90일 / 연간"), 우측 상단 "PDF 내보내기" · "Excel 내보내기" 버튼
+ 2. **KPI 카드 3~4개(상단 밴드)**: [운영사 관점] 홀 가동률 78% · 매출(임대+유틸+옥션 수수료) ₩1.24B · ㎡당 수익(RevPAD) · 참가사 리텐션(재참가율) — 각 카드에 전기 대비 델타(▲/▼)와 §1-4 상태색. [참가업체 관점] 총 방문(부스) · 평균 체류시간 · 매칭 성공률(AiLabel "AI 매칭") 등
+ 3. **히어로 — 추세 차트(2/3 폭)**: "매출 구성 추이"(운영사) 또는 "참가업체 vs 바이어 매칭 추이"(참가업체) — **Recharts `LineChart`/`AreaChart`**(다계열), 기간 셀렉트 연동. AI 예측 구간은 점선 + AiLabel "AI 수요예측"
+ 4. 우측(1/3) — **부문 분석**: "홀·업종별 구성" 가로 막대 리스트(Recharts `BarChart` 또는 progress 바) — 기술/IT 45% · 제조 28% · 헬스케어 15% · 유통 12%
+ 5. 하단(전폭) — **성과 테이블**: [운영사] 홀·행사별 P&L(행사, 홀, 매출, 공헌이익, 마진율, 상태 §1-4 StatusBadge) / [참가업체] 상위 참가사(업체명, 부스 위치, 방문 수, 매칭 수, 성과 배지 "우수/양호/보통/검토필요"). 지브라 스트라이프·sticky 헤더(§1-4)
+- **핵심 컴포넌트/상태**: KPI 카드(전기 대비 델타 칩) · Recharts 차트(라이트/다크 테마 토큰 연동, tabular numerals) · StatusBadge/성과 배지 재사용 · AiLabel(수요예측·이상탐지·매칭). 로딩 — KPI·차트 스켈레톤 · 빈 상태 — "집계할 데이터가 없습니다 — 행사 종료 후 지표가 채워집니다" · 에러 — 카드별 재시도.
+- **데이터 원천 (실/샘플 경계면)**: **대부분 샘플 시연.** M16 BI 데이터마트(스타 스키마 FactBooking·FactSettlement·FactUtility·FactAuction·FactVisitor + Dim*)·`KpiSnapshot` 집계 파이프라인은 **DA 후속 트랙 미구축**이므로(PLANNING §5A M16-1) 집계·예측·RevPAD·리텐션·P&L·매칭 지표는 샘플로 시연한다. 원천 목록(행사·부스·정산 레코드)은 실 API 부분 가능하나 **BI 지표는 집계 API 부재 → 샘플**(SCR-02 주최자 대시보드 KPI와 동일 원칙).
+- **Stitch 프롬프트**:
+
+```
+An enterprise Business Intelligence analytics dashboard for a venue operator, part of "KINTEX AI 전시관리" B2B web app. Desktop 1440px, light theme, white cards on #F9FAFB, primary blue #0066B3, purple #6D4AFF for AI elements, Korean sans-serif (Pretendard style). All UI text in Korean. Left sidebar 240px (Dashboard, 전시 일정, 홀 운영, 경영분석 highlighted). Main top header: title "경영분석" with subtitle "킨텍스 운영 수익성 · 참가업체 인사이트", a perspective toggle "[운영사] / [참가업체]" (운영사 selected), a period select "이번 행사 ▾", and two outlined buttons "PDF 내보내기" and "Excel 내보내기". Below, a bento grid. Top band: 3 KPI stat cards — "홀 가동률 78%" with a green ▲ delta chip "+4%p", "매출 ₩1.24B" with green ▲ "+12.5%", "㎡당 수익(RevPAD) ₩58,200" — each card with a small icon and tabular-number figure. Middle row: a large chart card (2/3 width) titled "매출 구성 추이" showing a multi-series line/area chart in blue and slate with a dashed forecast segment on the right end labeled with a small purple chip "AI 수요예측", plus a period dropdown "최근 90일"; a right card (1/3) titled "업종별 구성" with horizontal bar rows "기술·IT 45%", "제조 28%", "헬스케어 15%", "유통 12%" using blue bars of varying widths and mono-number percentages. Bottom (full width): a dense data table "홀·행사별 손익(P&L)" with columns 행사, 홀, 매출, 공헌이익, 마진율, 상태 — status pill badges (녹색 "우수", 파랑 "양호", 주황 "보통", 빨강 "검토필요"), zebra striped rows, sticky header. Data-rich executive analytics aesthetic, clear number typography.
+```
+
+- **라우트**: 운영사(테넌트 전역 크로스-행사) `/analytics` · 행사 P&L 드릴다운 `/events/:eventId/analytics` · 참가업체 관점 `/events/:eventId/booths/:boothId/analytics`. MDI 적용(주최자·운영 — §2.7-6).
+
+---
+
+### SCR-14 홀 현장운영 대시보드 (혼잡·에너지·주차) [M14]
+
+- **대상**: 홀매니저·킨텍스 운영 · **진입 경로**: 운영 대시보드(`ops.`) 사이드바 → "홀 운영" (행사 진행 중 상시 모니터)
+- **모듈·우선순위**: M14 현장운영 · **P2**(PLANNING §5A M14). 초기 범위는 **M4(전력 부하)·M10(체크인 혼잡) 파생 데이터 + 수기 입력** 결합이며, CCTV/센서/IoT 실시간은 킨텍스 시설 인프라 의존(후속).
+- **레이아웃 (위→아래)**:
+ 1. 헤더: 타이틀 "홀 현장운영" + 부제 "실시간 시설 모니터링 및 자원 최적화" + 우측 [실시간] / [이력 조회] 토글
+ 2. **12컬럼 벤토 그리드 — 히어로: 혼잡도 맵(span 8, 높이 500)**: 홀 도면 위 혼잡 히트(홀별 셀 Hall1~5, 임계 홀은 error 하이라이트 "홀3(혼잡)"), 하단 범례(원활 녹 / 보통 주황 / 혼잡 빨강)와 총 추정 인원. 전시장1/전시장2 홀 그룹 셀렉트. **데이터 미연동 시 상단 배지 "센서 미연동 · 체크인(M10) 파생/샘플"**
+ 3. 우측(span 4) — **에너지·환경**: HVAC 최적화 카드(평균 온도 22.5°C, 전력 부하 4.2MW, 상태 배지 "최적"), 조명존 카드(전시홀 85% / 공용부 100%, 자동 디밍 토글) — 게이지·진행 바
+ 4. 하단(span 12) — **주차 점유**: 4개 존 카드(존A 지하 98% error / 존B 옥외남측 75% warning / 존C 옥외북측 42% success / 하역장 20%), 각 카드 하단 점유율 바 + "N / 총면수" — iparking 연계 표기
+- **핵심 컴포넌트/상태**: 히트맵(도면 오버레이·범례) · 게이지/진행 바(Recharts `RadialBar` 또는 progress) · 존 점유 카드(임계 상태색 §1-4) · 이상 시 알림 배지. 로딩 — 위젯 스켈레톤 · 빈 상태 — "진행 중인 행사가 없습니다 — 운영 데이터는 개장 시 활성화됩니다" · 에러 — 위젯별 "데이터 원본 연결 안 됨" 안내.
+- **데이터 원천 (실/샘플 경계면)**: **샘플 시연 중심.** CCTV·혼잡 센서·HVAC/전력계·iparking·조명 IoT는 **미연동**(PLANNING §5A M14 "센서·IoT 연동은 킨텍스 시설 인프라 의존"). 혼잡은 M10 체크인 파생, 전력은 M4 신청 부하 집계로 **해당 모듈 구현 후 실 데이터 가능**하나 현 시점 위젯은 샘플. 하드웨어 연동 착수 금지(§2.6 갱신).
+- **Stitch 프롬프트**:
+
+```
+A real-time hall operations dashboard for a KINTEX exhibition-center facility manager, Korean B2B internal tool, desktop 1440px, light theme, blue #0066B3, Korean sans-serif. All UI text in Korean. Left sidebar 240px (홀 운영 highlighted). Header: title "홀 현장운영" with subtitle "실시간 시설 모니터링 및 자원 최적화" and a segmented toggle "[실시간] / [이력 조회]". A 12-column bento grid. Hero card (span 8, tall ~500px): "실시간 혼잡도 히트맵" — a top-down hall layout with a 5-cell grid labeled Hall 1–5, soft colored heat blobs (green/orange/red) blurred over it, Hall 3 highlighted red with label "홀3 (혼잡)", a hall-group select "홀 1-5 (제1전시장) ▾", a small top-left badge "센서 미연동 · 체크인 파생/샘플", and a bottom legend "원활 / 보통 / 혼잡" plus "총 추정 인원 14,250". Right column (span 4): a "HVAC 최적화" card showing "22.5°C 평균온도", a progress bar, "전력 부하 4.2MW", and a green status pill "최적"; below it a "조명 존" card with rows "전시홀 85%", "공용부 100%" with bars and an "자동 디밍" toggle switch. Bottom (span 12): "주차 점유 현황" with 4 zone cards — "존A(지하) 98%" red, "존B(옥외남) 75%" amber, "존C(옥외북) 42%" green, "하역장 20%", each with an occupancy bar and "1,176 / 1,200" style counts. Dense real-time operations monitoring aesthetic.
+```
+
+- **라우트**: `/ops/operations` (테넌트·운영 전역, 홀매니저) · 행사 진행 중 스코프 `/events/:eventId/operations`. MDI 적용(홀매니저 — §2.7-6).
+
+---
+
+### SCR-15 전시 일정 관리 (행사 캘린더 + 홀 가동) [M1·M6]
+
+- **대상**: 주최자·킨텍스 운영사 · **진입 경로**: 콘솔/운영 대시보드 사이드바 → "전시 일정"
+- **모듈·우선순위**: M1 홀 배정·행사일정(가용성 캘린더) + M6 마일스톤 · **P1**. 방문객용 세션 편성이 아니라 **운영사·주최자 관점의 전 행사 일정·홀 점유 관리 화면**(§2.6 갱신 재분류).
+- **레이아웃 (위→아래)**:
+ 1. 헤더: 타이틀 "전시 일정" + 부제 "킨텍스 전 홀 행사 일정 관리·모니터링"
+ 2. 필터/컨트롤 바: 홀 셀렉트(전체 홀 1-10 / 홀별) · 카테고리(전시/문화·예술/무역·산업/기술) · 상태(예정/진행중/종료) + 우측 [목록] / [캘린더] 뷰 토글
+ 3. **좌측 2/3 — 행사 리스트**: 행사 카드(포스터 썸네일, 행사명, 상태 배지 §1-4 "진행중/예정/종료", 카테고리, 기간, 배정 홀, 추정 인원, [상세 편집]·[반입/물류 보기] 버튼)
+ 4. 우측 1/3 — **미니 캘린더**(월 이동, 오늘·행사일 하이라이트) + **홀 가동률 요약**(홀1-3 85% · 홀4-5 40% 진행 바)
+- **핵심 컴포넌트/상태**: 행사 카드 리스트·미니 캘린더(월 그리드)·가동률 진행 바·StatusBadge 재사용·DdayChip(개장 임박). 로딩 — 카드 스켈레톤 · 빈 상태 — "등록된 행사가 없습니다 — 새 행사를 생성하세요" CTA · 에러 — 리스트 로드 실패 배너.
+- **데이터 원천 (실/샘플 경계면)**: **부분 실 API + 부분 샘플.** 행사(Event) 목록·기간·배정 홀은 **실 API 가능**(Event 엔티티 존재). 반면 **홀 가동률 집계·외부 행사일정 시스템 연동은 미구현 → 샘플**. 캘린더 점유 매트릭스는 배정(M1) 데이터 정합 후 실 전환.
+- **Stitch 프롬프트**:
+
+```
+An exhibition schedule management screen for a venue operator, Korean B2B web app "KINTEX AI 전시관리", desktop 1440px, light theme, blue #0066B3, Korean sans-serif. All UI text in Korean. Left sidebar 240px (전시 일정 highlighted). Header: title "전시 일정" with subtitle "킨텍스 전 홀 행사 일정 관리·모니터링". A filter bar: three selects "전체 홀 (1-10) ▾", "전체 카테고리 ▾", "전체 상태 ▾", and on the right a view toggle "[목록] / [캘린더]". Main grid: left 2/3 a vertical list of event cards, each card with a poster thumbnail on the left and details on the right — event title "스마트팩토리 코리아", a status pill ("진행중" green or "예정" amber), category "무역·산업 전시", a row of meta with icons "2026.09.05–09.08", "홀 4, 5", "추정 25,000명", and two small buttons "상세 편집" and "반입/물류 보기". Right 1/3 column: a mini month calendar "2026년 8월" with prev/next chevrons and a highlighted date "15", and below it a "홀 가동률 (8월)" card with progress bars "홀 1-3 85%" and "홀 4-5 40%". Clean scheduling/console aesthetic, dense but organized.
+```
+
+- **라우트**: `/schedule` (테넌트 전역, 운영·주최자) · 캘린더 딥링크 `/schedule/calendar`. MDI 적용(주최자·운영 — §2.7-6).
+
+---
+
+### SCR-16 관리자 대시보드 (백오피스 진입 · 시스템 개요) [M18]
+
+- **대상**: 테넌트(전시관) 관리자·플랫폼 슈퍼관리자 · **진입 경로**: 백오피스(`admin.`) 로그인 후 기본 홈
+- **모듈·우선순위**: M18 관리자 시스템(백오피스) · **P1**(PLANNING §5A M18·§5B). 본 화면은 **admin 랜딩 대시보드(시스템 개요)**이며, M18 본체(사용자관리·역할/권한 RBAC·공통코드·메뉴·감사로그·시스템설정·킨텍스 마스터데이터·룰셋 버전)는 **UIWS 표준 `system` 모듈 화면**으로 별도(§5B-1) — 후속 화면 세트로 추가. 플랫폼 슈퍼관리자는 상단 **테넌트 스위처** 보유, 테넌트 관리자는 자기 전시관 고정(§1A-4).
+- **레이아웃 (위→아래)**:
+ 1. 헤더: 타이틀 "시스템 개요" + 부제 "실시간 지표 및 운영 상태" + 우측 상태 인디케이터("시스템 정상" 녹색 점) + (플랫폼 슈퍼관리자) 테넌트 스위처 드롭다운
+ 2. **KPI 카드 3개**: 진행 행사(활성) 14 (▲+2) · 실시간 방문객 24,592 (▲+12%) · 주차 가용 18% (혼잡)
+ 3. **차트(2/3 폭)**: "방문객 추이(오늘)" — **Recharts `BarChart`**(시간대 09:00~19:00, [오늘]/[주간] 토글), 호버 툴팁
+ 4. 우측(1/3) — **진행 중 이벤트 리스트**: 카드(썸네일, "LIVE" 상태 점, 행사명, 홀·시간) + "준비중" 카드(진행 바)
+ 5. (선택) 우하단 플로팅 AI 어시스턴트 버튼 — **범위 표기: AI 컨시어지는 P2/후속 트랙**(PLANNING M18 미포함), 기본은 숨김/비활성
+- **핵심 컴포넌트/상태**: KPI 카드(델타 칩)·Recharts 막대 차트·라이브 이벤트 카드(상태 점)·StatusBadge. 로딩 — 스켈레톤 · 빈 상태 — "진행 중인 행사가 없습니다" · 에러 — 위젯별 재시도. RBAC: 테넌트 관리자 vs 플랫폼 슈퍼관리자 위젯 차등(크로스-테넌트 집계는 슈퍼관리자만).
+- **데이터 원천 (실/샘플 경계면)**: **혼합.** 사용자 수·활성 행사 수 등 **일부 실 API 가능**(M18/시스템관리 엔티티). **실시간 방문객·주차·라이브 이벤트·시간대 추이 위젯은 집계/센서 미구축 → 샘플 시연.** 플로팅 AI 봇은 미구현(비노출 기본).
+- **Stitch 프롬프트**:
+
+```
+An admin back-office overview dashboard for "KINTEX AI 전시관리" platform, Korean B2B internal tool, desktop 1440px, light theme, blue #0066B3, Korean sans-serif. All UI text in Korean. Left sidebar 240px with menu (Dashboard highlighted, 전시 일정, 홀 운영, 경영분석) and a "Create New Event" button near the bottom with Settings/Support and an "Admin Profile" row. Header: title "시스템 개요" with subtitle "실시간 지표 및 운영 상태" and a small right-aligned status indicator "● 시스템 정상" in green (plus, for super admin, a tenant switcher dropdown "KINTEX ▾"). Top band: 3 KPI cards — "진행 행사(활성) 14" with a green chip "+2 this week", "실시간 방문객 24,592" with green "+12% vs 어제", "주차 가용 18%" with an amber chip "혼잡" and a thin progress bar. Below: a 2/3-width chart card "방문객 추이 (오늘)" with a bar chart across hours 09:00–19:00 (blue bars of varying heights, hover tooltip showing values) and a "[오늘] / [주간]" toggle; a 1/3-width column "진행 중 이벤트" with event cards each showing a thumbnail, a green "LIVE NOW" dot, event title, hall + time, and one "준비중" card with an amber progress bar. Optional small floating circular assistant button bottom-right (kept subtle). Clean operational admin aesthetic.
+```
+
+- **라우트**: `/admin` (백오피스 랜딩, 테넌트 스코프 고정) · 슈퍼관리자 테넌트 스위처는 컨텍스트 전환. M18 본체 화면(별도): `/admin/users`·`/admin/roles`·`/admin/codes`·`/admin/menus`·`/admin/audit`·`/admin/settings`·`/admin/masterdata/*`(홀·요율·룰셋). MDI 적용(관리자 — §2.7-6).
+
+---
+
+### SCR-17 컴포넌트 가이드 (디자인 시스템 스타일가이드) [§1 실증]
+
+- **대상**: 디자이너·프론트 개발(kintex-frontend-dev) · **진입 경로**: 내부 스타일가이드 URL(제품 내비 미노출)
+- **성격**: **§1 디자인 시스템의 실증 스타일가이드(스토리북 성격).** 제품 화면이 아니라 §1 토큰·컴포넌트가 실제로 어떻게 렌더되는지 보여주는 **단일 참조**다. Stitch `component_guide_updated`(최신본)를 근거로 하되, **색·치수의 권위는 §1**(본 문서)이다.
+- **레이아웃 (벤토 섹션)**:
+ 1. 헤더: "System Reference / 컴포넌트 가이드", 설명("KINTEX AI 디자인 시스템 — 고신뢰·정밀 정보 처리 B2B 전시 환경"), 버전 배지
+ 2. **타이포그래피 & 컬러**: Pretendard 스케일(Display 28-36 / Headline 24 / Title/H3 16-18 / Body 14) 한국어 샘플 + 팔레트 스와치(주 브랜드 블루·AI 액센트 `#6D4AFF`·Success·Error·Neutral)
+ 3. **AI 전용 요소**: "AI 초안 컴포넌트"(좌측 4px 보라 액센트·워터마크 샘플 영역), 위반 플래그 핀(피난 통로 차단·바닥하중 초과)
+ 4. **버튼 & 액션**: Primary / Secondary Outlined / Ghost / **AI 제안(보라)** / Disabled / 아이콘 버튼(편집·삭제·공유)
+ 5. **상태 배지 & 칩**: 생애주기 `작성중→제출됨→AI검토(보라)→승인→반려→시공중→검수완료`(§1-4와 1:1) + DdayChip(D-3 warning)·Hall 칩·High Traffic 칩
+ 6. **시스템 아이콘 라이브러리(커스텀 SVG)**: Dashboard·Calendar·Operations·Analytics·Search·Menu·AI Bot (stroke 스타일)
+ 7. **데이터 시각화**: 게이지(점유율 78% 임계치 85%)·혼잡도 히트맵 범례(매우혼잡·다소혼잡·원활)·주간 추이 미니 막대 — 실제 구현은 **Recharts**로 대체
+ 8. **폼 요소**: Input(기본/포커스/에러)·Dropdown·Checkbox·Radio
+ 9. **피드백 & 오버레이**: Toast·Alert·마이크로 모달
+- **§1 정합 주의(권위=본 문서)**: 스타일가이드가 표기한 일부 값은 §1과 미세 상이 — **KINTEX Blue `#004E8B`**(가이드) ≈ 본 문서 `primary-700 #004C86`(헤더/hover 짙은 톤)이며 **주 브랜드 블루는 `primary-600 #0066B3` 유지**(§1-2). **Success `#00734E`/Error `#BA1A1A`/히트맵 `#D92D20`·`#F79009`·`#12B76A`**는 Stitch Material 팔레트값이므로, 구현은 **§1 토큰(`success #0E8A5F`·`error #D92D20`)을 권위로 사용**하고 가이드값은 시각 참조로만 둔다. **AI 액센트 `#6D4AFF`·상태 배지 진행·라운드 4/8px·pill·좌측 액센트 바는 §1과 일치**(실증 확인).
+- **데이터 원천 (실/샘플 경계면)**: **해당 없음(N/A) — 정적 참조.** 실 데이터·API 없음. 내부 문서/스토리북으로만 유지하며 배포 제품 라우트로 노출하지 않는다.
+- **Stitch 프롬프트**:
+
+```
+A design-system style guide / component reference page for "KINTEX AI 전시관리", a Korean B2B exhibition platform. Desktop 1440px, light theme, primary blue #0066B3, AI accent purple #6D4AFF, backgrounds #F9FAFB, 1px borders #E4E7EC, Korean sans-serif (Pretendard). All UI text in Korean where shown. A bento grid of white bordered section cards, each with a left 4px colored accent bar and a small title. Sections: (1) "타이포그래피 & 컬러" — a Pretendard type scale with Korean samples "전시공간 최적화 엔진" (Display), "도면 분석 보고서" (Headline), "부스 배치 시뮬레이션" (Title), body text; and a color swatch grid "KINTEX Blue", "AI Accent #6D4AFF", "Success", "Error". (2) "AI 전용 요소" — an "AI 초안 컴포넌트" card with a faint diagonal "AI GENERATED" watermark area and violation flag map pins "피난 통로 차단", "바닥하중 초과" in red. (3) "버튼 & 액션" — Primary, Secondary Outlined, Ghost, a purple "AI 제안 레이아웃" button, a disabled button, and edit/delete/share icon buttons. (4) "상태 배지 & 칩" — lifecycle status chips in a row with left accent bars: "작성중"(gray), "제출됨"(blue), "AI검토"(purple), "승인"(green), "반려"(red), plus "시공중", "검수완료", and small chips "D-3", "Hall 1A", "High Traffic". (5) "데이터 시각화" — an occupancy gauge "전시장 점유율 78% / 임계치 85%", a heatmap legend "매우 혼잡 / 다소 혼잡 / 원활", and a small weekly bar chart. (6) "폼 요소" — text input (default/focus/error states), dropdown, checkbox, radio. (7) "피드백 & 오버레이" — a dark toast "데이터가 저장되었습니다", a red alert "소방법 위반 구역 3곳", and a small confirm modal. Clean, systematic, storybook-style reference layout, high density.
+```
+
+- **라우트**: `/_styleguide` (내부 전용, 프로덕션 비노출) — 제품 내비게이션·사이드바에 포함하지 않는다.
+
+---
+
## 4. 모바일 대응 (390px)
모바일은 **조회·승인·현장** 시나리오 전용(PLANNING.md §8). 캔버스 편집(SCR-03, 07)과 스펙 편집(SCR-06 좌패널)은 모바일 미제공 — 뷰어+승인 액션만. 아래 두 화면은 **모바일 전용 신규 화면**, 나머지는 반응형 축소.
@@ -540,4 +670,5 @@ A mobile field inspection screen for a KINTEX hall manager verifying booth const
| v1.0 | 2026-07-11 | designer | 최초 작성 — PLANNING.md v1.0 기반. 디자인 시스템·IA·P0 중심 14화면(웹 12 + 모바일 2) Stitch 프롬프트 포함. 다크모드는 Phase 1 미지원(캔버스 다크 서피스만) 결정 |
| v1.0.1 | 2026-07-11 | reviewer 반영 | 화면 수 표기 정정(13→14). 잔여 지적사항은 docs/BACKLOG.md 참조 |
| v1.1 | 2026-07-11 | designer | **Stitch 산출물 학습·정합화.** `stitch_kintex_ai_system_architect/` 18화면 code.html + DESIGN.md 3변형(Intelligence·Nexus·Precision) 학습. ①§1-2 컬러: Precision Enterprise AI 변형이 우리 토큰(#0066B3·#1C2536·#6D4AFF·#D92D20·#F9FAFB·#101828·StatusBadge 진행) 실증 확인 — 우리 팔레트를 단일 출처로 유지, #0059A6·#00427D는 짙은 대체 톤으로만 허용, ai-surface #F5F3FF AI 카드 배경 채택. ②§1-3 타이포: Pretendard 권위 유지, Inter를 라틴/tabular 보조로 허용(Stitch가 Hanken Grotesk/Inter 채택), 행 높이 44/48px 권위값 유지. ③§1-4 라운드(4/8px·pill)·엘리베이션(톤레이어+1px 테두리+AI 좌측 보라 액센트)·그리드(12컬럼·1440px·4px 베이스)·지브라 테이블 토큰 신설(이전 누락분). ④§2.5 Stitch 화면↔SCR 매핑표 신설(14화면). ⑤§2.6 범위 게이트 — proposal.md 및 범위 밖 4화면(business_intelligence·hall_operations·exhibition_schedule·admin_dashboard)을 P2 후보로 분류(PLANNING이 범위 권위, designer 임의 승격 금지). PLANNING.md·타 문서 무수정 |
+| v1.3 | 2026-07-11 | designer | **v2.0 확장 화면 SCR-13~17 정합화.** Stitch 재취득 5화면(`business_intelligence`·`hall_operations`·`exhibition_schedule`·`admin_dashboard`·`component_guide_updated`)을 기존 SCR 형식대로 순증. ①§2.5-1 v2.0 확장 화면 매핑표 신설(SCR-13 M16 P1·SCR-14 M14 P2·SCR-15 M1·M6 P1·SCR-16 M18 P1·SCR-17 §1 스타일가이드) + 공통 NFR(테마·웹접근성·다국어·AI 라벨). ②§2.6 갱신 노트 — business_intelligence/hall_operations/admin_dashboard는 planner의 PLANNING §5A 정식 반영(M16/M14/M18)으로 P2 후보 게이트 통과, exhibition_schedule은 운영사·주최자용 행사일정으로 재분류(M1·M6). 비전성 요소(센서·CCTV·AI 컨시어지)는 P2/후속으로 범위 표기. ③§3에 SCR-13~17 상세(레이아웃·상태·데이터 원천 실/샘플 경계면·라우트·Stitch 영어 프롬프트) 추가 — BI 차트 Recharts, StatusBadge/AiLabel 등 공통 자산 재사용 명시, 집계/센서 API 부재분은 샘플 시연 표기(SCR-02 원칙 준수). 라우트는 App.tsx 컨벤션 정합(`/analytics`·`/ops/operations`·`/schedule`·`/admin`·`/_styleguide` + event 스코프 드릴다운). §1 토큰 권위 유지(신규 토큰 0), PLANNING.md·src/ 무수정 |
| v1.2 | 2026-07-11 | designer | **MDI(다중 문서 인터페이스) 셸 표준 신설.** 업무 포털 AppShell을 단일 라우트 SPA → 탭 호스트로 전환하는 표준을 §2.7로 정의(kintex-frontend-dev AppShell 전환 기준). ①§2-2 내비게이션을 MDI 기준으로 갱신(사이드바+상단 문서 탭바+중앙 DocumentHost, 메뉴 클릭=탭 열기, 공개/관람객 사이트·모바일은 MDI 비적용). ②§2.7 신설 — 2.7-1 셸 레이아웃(3영역 그리드) · 2.7-2 탭 규격(열기/활성/닫기·미들클릭·드래그 재정렬·중복방지·최대 12탭·오버플로우 스크롤+드롭다운·dirty ● 및 닫기 확인·핀 고정) · 2.7-3 탭별 상태 보존(비활성 언마운트 금지 display:none·캔버스 freeze·WebGL 메모리 가드·beforeunload) · 2.7-4 세션 복원 & 딥링크↔탭 URL 동기화(라우트 예시·localStorage 세션·행사 전환 분리) · 2.7-5 단축키(Ctrl+W/Tab/1~9/Shift+T·Ctrl+클릭 새 탭)+접근성(ARIA tablist/tab/tabpanel·로빙 탭인덱스·WCAG AA) · 2.7-6 역할별 적용(관리자·주최자·참가·장치·홀매니저=적용, 관람객/공개=비적용, 모바일 전역 비적용) · 2.7-7 컴포넌트·스토어 표준(AppShell·TabBar·Tab·DocumentHost·useMdiStore/DocumentInstance/docKey 중복방지·직렬화 규칙) + MDI 셸 Stitch 프롬프트(영어). §1 토큰 재사용, 신규 토큰 0. PLANNING.md·src/·타 문서 무수정 |
diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json
index 6f04bcd..89fa22b 100644
--- a/src/frontend/package-lock.json
+++ b/src/frontend/package-lock.json
@@ -13,6 +13,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.26.2",
+ "recharts": "^3.9.2",
"sockjs-client": "^1.6.1",
"zustand": "^4.5.5"
},
@@ -750,6 +751,32 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@reduxjs/toolkit": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz",
+ "integrity": "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==",
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.0.0",
+ "@standard-schema/utils": "^0.3.0",
+ "immer": "^11.0.0",
+ "redux": "^5.0.1",
+ "redux-thunk": "^3.1.0",
+ "reselect": "^5.1.0"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
+ "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@remix-run/router": {
"version": "1.23.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.3.tgz",
@@ -1116,6 +1143,18 @@
"win32"
]
},
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
+ "license": "MIT"
+ },
+ "node_modules/@standard-schema/utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
+ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
+ "license": "MIT"
+ },
"node_modules/@stomp/stompjs": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@stomp/stompjs/-/stompjs-7.3.0.tgz",
@@ -1193,6 +1232,69 @@
"@babel/types": "^7.28.2"
}
},
+ "node_modules/@types/d3-array": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz",
+ "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
+ "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
+ "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz",
+ "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
+ "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
+ "license": "MIT"
+ },
"node_modules/@types/estree": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
@@ -1247,6 +1349,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
+ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
+ "license": "MIT"
+ },
"node_modules/@vitejs/plugin-react": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
@@ -1337,6 +1445,15 @@
],
"license": "CC-BY-4.0"
},
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -1351,6 +1468,127 @@
"devOptional": true,
"license": "MIT"
},
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "license": "ISC",
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
+ "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-time": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -1369,6 +1607,12 @@
}
}
},
+ "node_modules/decimal.js-light": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
+ "license": "MIT"
+ },
"node_modules/electron-to-chromium": {
"version": "1.5.389",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.389.tgz",
@@ -1376,6 +1620,16 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/es-toolkit": {
+ "version": "1.49.0",
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.49.0.tgz",
+ "integrity": "sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g==",
+ "license": "MIT",
+ "workspaces": [
+ "docs",
+ "benchmarks"
+ ]
+ },
"node_modules/esbuild": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
@@ -1425,6 +1679,12 @@
"node": ">=6"
}
},
+ "node_modules/eventemitter3": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz",
+ "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
+ "license": "MIT"
+ },
"node_modules/eventsource": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-2.0.2.tgz",
@@ -1477,12 +1737,32 @@
"integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
"license": "MIT"
},
+ "node_modules/immer": {
+ "version": "11.1.11",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.11.tgz",
+ "integrity": "sha512-qzXuyXAkPySAGYkfsAwodDPWT8Zm7/Uo5BNt4BjhMhG5WlWyZZ4wQqnWwdS8kjlQ1Cwu6gjw3A6+0gTQwlyYtw==",
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -1641,6 +1921,37 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-is": {
+ "version": "19.2.7",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz",
+ "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/react-redux": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz",
+ "integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.6",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.2.25 || ^19",
+ "react": "^18.0 || ^19",
+ "redux": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-refresh": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
@@ -1683,12 +1994,64 @@
"react-dom": ">=16.8"
}
},
+ "node_modules/recharts": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.9.2.tgz",
+ "integrity": "sha512-G4fy+Pk46RaXgwWMh+Nzhyo/lbFAVqXo9gtetlyehe6Ehge9CsgDuOTwQDD+i1+llaLktNBiNq4bhnGlDRXFtw==",
+ "license": "MIT",
+ "workspaces": [
+ "www"
+ ],
+ "dependencies": {
+ "@reduxjs/toolkit": "^1.9.0 || 2.x.x",
+ "clsx": "^2.1.1",
+ "decimal.js-light": "^2.5.1",
+ "es-toolkit": "^1.39.3",
+ "eventemitter3": "^5.0.1",
+ "immer": "^11.1.8",
+ "react-redux": "8.x.x || 9.x.x",
+ "reselect": "5.2.0",
+ "tiny-invariant": "^1.3.3",
+ "use-sync-external-store": "^1.2.2",
+ "victory-vendor": "^37.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/redux": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
+ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/redux-thunk": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
+ "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "redux": "^5.0.0"
+ }
+ },
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
"license": "MIT"
},
+ "node_modules/reselect": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.2.0.tgz",
+ "integrity": "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==",
+ "license": "MIT"
+ },
"node_modules/rollup": {
"version": "4.62.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz",
@@ -1811,6 +2174,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
+ "license": "MIT"
+ },
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
@@ -1882,6 +2251,28 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
+ "node_modules/victory-vendor": {
+ "version": "37.3.6",
+ "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz",
+ "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==",
+ "license": "MIT AND ISC",
+ "dependencies": {
+ "@types/d3-array": "^3.0.3",
+ "@types/d3-ease": "^3.0.0",
+ "@types/d3-interpolate": "^3.0.1",
+ "@types/d3-scale": "^4.0.2",
+ "@types/d3-shape": "^3.1.0",
+ "@types/d3-time": "^3.0.0",
+ "@types/d3-timer": "^3.0.0",
+ "d3-array": "^3.1.6",
+ "d3-ease": "^3.0.1",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-shape": "^3.1.0",
+ "d3-time": "^3.0.0",
+ "d3-timer": "^3.0.1"
+ }
+ },
"node_modules/vite": {
"version": "5.4.21",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
diff --git a/src/frontend/package.json b/src/frontend/package.json
index 19865c0..f7651b4 100644
--- a/src/frontend/package.json
+++ b/src/frontend/package.json
@@ -17,6 +17,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.26.2",
+ "recharts": "^3.9.2",
"sockjs-client": "^1.6.1",
"zustand": "^4.5.5"
},
diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx
index d21b84f..f6e1f40 100644
--- a/src/frontend/src/App.tsx
+++ b/src/frontend/src/App.tsx
@@ -12,6 +12,11 @@ import { ComplianceReportPage } from './screens/compliance/ComplianceReportPage'
import { ManagerApprovalQueuePage } from './screens/approval/ManagerApprovalQueuePage';
import { ReviewDetailsPage } from './screens/approval/ReviewDetailsPage';
import { VisualizationGalleryPage } from './screens/gallery/VisualizationGalleryPage';
+import { AnalyticsDashboardPage } from './screens/analytics/AnalyticsDashboardPage';
+import { HallOperationsPage } from './screens/ops/HallOperationsPage';
+import { ExhibitionSchedulePage } from './screens/schedule/ExhibitionSchedulePage';
+import { AdminDashboardPage } from './screens/admin/AdminDashboardPage';
+import { ComponentGuidePage } from './screens/styleguide/ComponentGuidePage';
import { ContractorOnsiteChecklistPage } from './screens/mobile/ContractorOnsiteChecklistPage';
import { ManagerFieldInspectionPage } from './screens/mobile/ManagerFieldInspectionPage';
import { AppShell } from './components/layout/AppShell';
@@ -79,6 +84,16 @@ export function App() {
path="/events/:eventId/booths/:boothId/gallery"
element={}
/>
+ {/* SCR-13 경영분석 대시보드 (M16 BI · 테넌트 전역) */}
+ } />
+ {/* SCR-14 홀 현장운영 대시보드 (M14) */}
+ } />
+ {/* SCR-15 전시 일정 관리 (M1·M6) */}
+ } />
+ {/* SCR-16 관리자 대시보드 (M18 랜딩) */}
+ } />
+ {/* SCR-17 컴포넌트 가이드 (내부 전용 · 네비 비노출) */}
+ } />
{/* 모바일 전용 (390) — 셸 없이 전폭, 조회·현장 */}
diff --git a/src/frontend/src/components/layout/AppShell.tsx b/src/frontend/src/components/layout/AppShell.tsx
index 6b27749..d34422a 100644
--- a/src/frontend/src/components/layout/AppShell.tsx
+++ b/src/frontend/src/components/layout/AppShell.tsx
@@ -1,14 +1,23 @@
-import { Outlet } from 'react-router-dom';
+import { NavLink, Outlet } from 'react-router-dom';
import { useAuthStore } from '../../store/authStore';
import { DdayChip } from '../ui/Badge';
import './app-shell.css';
-const NAV_ITEMS = [
+/**
+ * 사이드바 항목. `to`가 있으면 react-router NavLink(활성 표시), 없으면 플레이스홀더(#).
+ * 플레이스홀더 항목(대시보드·플로어플랜 등)은 행사 스코프(:eventId) 라우트라 셸 밖에서 진입한다.
+ * 신규 4항목(경영분석·현장운영·전시 일정·관리자)은 테넌트 전역 라우트로 직접 배선.
+ */
+const NAV_ITEMS: { key: string; label: string; icon: string; to?: string }[] = [
{ key: 'dashboard', label: '대시보드', icon: '▦' },
{ key: 'floorplan', label: '플로어플랜 스튜디오', icon: '◱' },
{ key: 'exhibitors', label: '참가업체 관리', icon: '☷' },
+ { key: 'schedule', label: '전시 일정', icon: '▤', to: '/schedule' },
+ { key: 'operations', label: '현장운영', icon: '◐', to: '/ops/operations' },
+ { key: 'analytics', label: '경영분석', icon: '▨', to: '/analytics' },
{ key: 'documents', label: '서류·마일스톤', icon: '❒' },
{ key: 'settlement', label: '정산', icon: '₩' },
+ { key: 'admin', label: '관리자', icon: '⚙', to: '/admin' },
];
/**
@@ -39,12 +48,24 @@ export function AppShell() {
)}
diff --git a/src/frontend/src/screens/admin/AdminDashboardPage.tsx b/src/frontend/src/screens/admin/AdminDashboardPage.tsx
new file mode 100644
index 0000000..1793b8c
--- /dev/null
+++ b/src/frontend/src/screens/admin/AdminDashboardPage.tsx
@@ -0,0 +1,140 @@
+import { useState } from 'react';
+import {
+ Bar,
+ BarChart,
+ CartesianGrid,
+ ResponsiveContainer,
+ Tooltip,
+ XAxis,
+ YAxis,
+} from 'recharts';
+import { CHART } from '../chartColors';
+import {
+ ADMIN_KPIS,
+ LIVE_EVENTS,
+ TENANTS,
+ VISITOR_TREND,
+} from './sampleAdmin';
+import './admin.css';
+
+const MOCK = `${import.meta.env.BASE_URL}mock/organizer_dashboard`;
+const THUMBS = [`${MOCK}/img1.jpg`, `${MOCK}/img2.jpg`, `${MOCK}/img3.jpg`];
+
+/*
+ * SCR-16 관리자 대시보드 (M18 랜딩). Stitch admin_dashboard 이식.
+ * - 시스템 개요: KPI 3 + 방문객 추이 막대(오늘/주간) + 진행중 이벤트 리스트.
+ * ★ 경계면(혼합): 지표 대부분 샘플(집계/센서 미구축). 플로팅 AI 봇은 P2 → 미구현(비노출).
+ * M18 본체(사용자·역할·감사로그·설정)는 후속 화면 세트(/admin/*).
+ */
+export function AdminDashboardPage() {
+ const [range, setRange] = useState<'today' | 'weekly'>('today');
+ const [tenant, setTenant] = useState(TENANTS[0]);
+
+ return (
+
+
+
+
+ 집계 API 대기 (샘플)
+ 실시간 방문객·주차·추이 위젯은 시연용 샘플입니다. 시스템관리(M18) 지표는 후속 연동됩니다.
+
+
+
+ {ADMIN_KPIS.map((k) => (
+
+
{k.label}
+
{k.value}
+ {k.delta && (
+
+ {k.tone === 'warn' ? '⚠' : k.deltaDir === 'down' ? '▼' : '▲'} {k.delta}
+
+ )}
+ {k.bar != null && (
+
+
+
+ )}
+
+ ))}
+
+
+
+
+
+
방문객 추이 ({range === 'today' ? '오늘' : '주간 평균'})
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* 플로팅 AI 컨시어지 버튼: PLANNING M18 미포함 → P2/후속. 현재 비노출. */}
+
+ );
+}
+
+const TOOLTIP_STYLE = {
+ fontSize: 12,
+ borderRadius: 8,
+ border: '1px solid #E4E7EC',
+ boxShadow: '0 4px 12px rgba(16,24,40,0.1)',
+} as const;
diff --git a/src/frontend/src/screens/admin/admin.css b/src/frontend/src/screens/admin/admin.css
new file mode 100644
index 0000000..daa4ab5
--- /dev/null
+++ b/src/frontend/src/screens/admin/admin.css
@@ -0,0 +1,158 @@
+@import '../shared.css';
+
+.kx-admin {
+ flex: 1;
+ min-width: 0;
+ overflow-y: auto;
+ padding: var(--space-5);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-5);
+}
+
+.kx-admin__head {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: var(--space-4);
+ flex-wrap: wrap;
+}
+.kx-admin__title {
+ font-size: var(--fs-h1);
+ line-height: var(--lh-h1);
+ color: var(--color-neutral-900);
+}
+.kx-admin__subtitle {
+ font-size: var(--fs-body);
+ color: var(--color-neutral-500);
+ margin-top: 2px;
+}
+.kx-admin__head-actions {
+ display: flex;
+ align-items: center;
+ gap: var(--space-3);
+}
+.kx-admin__status {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ font-size: var(--fs-caption);
+ font-weight: 600;
+ color: var(--color-success);
+}
+.kx-admin__status-dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: var(--color-success);
+ box-shadow: 0 0 0 3px rgba(14, 138, 95, 0.15);
+}
+
+.kx-admin__degraded-bar {
+ display: flex;
+ align-items: center;
+ gap: var(--space-3);
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+ background: var(--color-neutral-050);
+ border: var(--border-card);
+ border-radius: var(--radius-sm);
+ padding: var(--space-2) var(--space-3);
+}
+
+.kx-admin__kpis {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: var(--space-4);
+}
+
+.kx-admin__split {
+ display: grid;
+ grid-template-columns: 2fr 1fr;
+ gap: var(--space-4);
+ align-items: start;
+}
+.kx-admin__chart {
+ width: 100%;
+}
+
+.kx-admin__live {
+ border: var(--border-card);
+ border-radius: var(--radius-lg);
+ background: var(--color-white);
+ padding: var(--space-4);
+}
+.kx-admin__live-list {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-3);
+}
+.kx-livecard {
+ display: flex;
+ gap: var(--space-3);
+ padding: var(--space-3);
+ border: var(--border-card);
+ border-radius: var(--radius-lg);
+ background: var(--color-neutral-050);
+}
+.kx-livecard__thumb {
+ width: 56px;
+ height: 56px;
+ flex-shrink: 0;
+ border-radius: var(--radius-sm);
+ background-size: cover;
+ background-position: center;
+ background-color: var(--color-neutral-100);
+}
+.kx-livecard__body {
+ flex: 1;
+ min-width: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+.kx-livecard__top {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+.kx-livecard__dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+}
+.kx-livecard__dot.is-live {
+ background: var(--color-error);
+ animation: kx-live 1.6s ease-in-out infinite;
+}
+.kx-livecard__dot.is-prep {
+ background: var(--color-violation-warn);
+}
+@keyframes kx-live {
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(217, 45, 32, 0.5); }
+ 50% { box-shadow: 0 0 0 5px rgba(217, 45, 32, 0); }
+}
+.kx-livecard__state {
+ font-size: 11px;
+ font-weight: 700;
+ letter-spacing: 0.02em;
+ color: var(--color-neutral-500);
+}
+.kx-livecard__title {
+ font-size: var(--fs-body);
+ font-weight: 600;
+ color: var(--color-neutral-900);
+}
+.kx-livecard__meta {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+}
+
+@media (max-width: 1100px) {
+ .kx-admin__kpis {
+ grid-template-columns: 1fr;
+ }
+ .kx-admin__split {
+ grid-template-columns: 1fr;
+ }
+}
diff --git a/src/frontend/src/screens/admin/sampleAdmin.ts b/src/frontend/src/screens/admin/sampleAdmin.ts
new file mode 100644
index 0000000..781d681
--- /dev/null
+++ b/src/frontend/src/screens/admin/sampleAdmin.ts
@@ -0,0 +1,58 @@
+/*
+ * 관리자 대시보드 표시 데이터 (SCR-16 · M18 랜딩).
+ * ★ 경계면(혼합): 사용자 수·활성 행사 수 등 일부는 M18/시스템관리 엔티티로 실 API 가능하나
+ * 집계 엔드포인트 미확정 → 현재 샘플. 실시간 방문객·주차·라이브 이벤트·시간대 추이는
+ * 집계/센서 미구축 → 샘플 시연. 플로팅 AI 봇(컨시어지)은 P2/후속 → 비노출.
+ */
+export interface AdminKpi {
+ key: string;
+ label: string;
+ value: string;
+ delta?: string;
+ deltaDir?: 'up' | 'down';
+ tone?: 'normal' | 'warn';
+ bar?: number; // 진행 바(%) 선택
+}
+
+export const ADMIN_KPIS: AdminKpi[] = [
+ { key: 'events', label: '진행 행사 (활성)', value: '14', delta: '+2 (금주)', deltaDir: 'up' },
+ { key: 'visitors', label: '실시간 방문객', value: '24,592', delta: '+12% (어제 대비)', deltaDir: 'up' },
+ { key: 'parking', label: '주차 가용', value: '18%', delta: '혼잡', tone: 'warn', bar: 82 },
+];
+
+// 방문객 추이(오늘) — 시간대별.
+export interface HourPoint {
+ hour: string;
+ today: number;
+ weekly: number;
+}
+export const VISITOR_TREND: HourPoint[] = [
+ { hour: '09시', today: 1200, weekly: 980 },
+ { hour: '10시', today: 2600, weekly: 2100 },
+ { hour: '11시', today: 3800, weekly: 3200 },
+ { hour: '12시', today: 3100, weekly: 2900 },
+ { hour: '13시', today: 3400, weekly: 3000 },
+ { hour: '14시', today: 4200, weekly: 3600 },
+ { hour: '15시', today: 4600, weekly: 3900 },
+ { hour: '16시', today: 4100, weekly: 3500 },
+ { hour: '17시', today: 3200, weekly: 2800 },
+ { hour: '18시', today: 1900, weekly: 1600 },
+ { hour: '19시', today: 900, weekly: 720 },
+];
+
+export interface LiveEvent {
+ id: string;
+ title: string;
+ hallTime: string;
+ live: boolean;
+ progress?: number; // 준비중 카드
+ thumbIdx: number;
+}
+export const LIVE_EVENTS: LiveEvent[] = [
+ { id: 'smf', title: '스마트팩토리 코리아', hallTime: '홀 4·5 · 10:00–18:00', live: true, thumbIdx: 0 },
+ { id: 'health', title: '국제 헬스케어 위크', hallTime: '홀 7 · 10:00–17:00', live: true, thumbIdx: 1 },
+ { id: 'foodtech', title: '푸드테크 엑스포 (준비중)', hallTime: '홀 3 · D-2 설치', live: false, progress: 64, thumbIdx: 2 },
+];
+
+// 슈퍼관리자 테넌트 스위처(샘플)
+export const TENANTS = ['KINTEX', 'BEXCO', 'COEX'];
diff --git a/src/frontend/src/screens/analytics/AnalyticsDashboardPage.tsx b/src/frontend/src/screens/analytics/AnalyticsDashboardPage.tsx
new file mode 100644
index 0000000..69a4972
--- /dev/null
+++ b/src/frontend/src/screens/analytics/AnalyticsDashboardPage.tsx
@@ -0,0 +1,246 @@
+import { useState } from 'react';
+import {
+ Area,
+ AreaChart,
+ CartesianGrid,
+ ResponsiveContainer,
+ Tooltip,
+ XAxis,
+ YAxis,
+} from 'recharts';
+import { AiLabel, StatusBadge } from '../../components/ui/Badge';
+import { Button } from '../../components/ui/Button';
+import { CHART } from '../chartColors';
+import {
+ EXHIBITOR_KPIS,
+ EXHIBITOR_PERF,
+ EXHIBITOR_TREND,
+ GRADE_LABEL,
+ OPERATOR_KPIS,
+ OPERATOR_PNL,
+ OPERATOR_TREND,
+ SECTORS,
+ type Kpi,
+ type Perspective,
+ type Period,
+} from './sampleAnalytics';
+import './analytics.css';
+
+/*
+ * SCR-13 경영분석 대시보드 (M16 BI). Stitch business_intelligence 이식.
+ * - 관점 토글(운영사/참가업체)로 KPI·추세·성과 테이블 격리 전환.
+ * ★ 경계면: BI 집계·예측 파이프라인 미구축(PLANNING §5A M16-1) → 전 지표 샘플 시연.
+ * (라우트 /analytics 는 테넌트 전역. 행사 P&L 드릴다운은 후속.)
+ */
+export function AnalyticsDashboardPage() {
+ const [perspective, setPerspective] = useState('operator');
+ const [period, setPeriod] = useState('event');
+
+ const isOperator = perspective === 'operator';
+ const kpis = isOperator ? OPERATOR_KPIS : EXHIBITOR_KPIS;
+
+ return (
+
+ {/* 헤더 */}
+
+
+
+ 집계 API 대기 (샘플)
+ BI 데이터마트·예측 파이프라인 미구축 — 아래 지표는 시연용 샘플입니다.
+
+
+ {/* KPI 밴드 */}
+
+ {kpis.map((k) => (
+
+ ))}
+
+
+ {/* 히어로 추세(2/3) + 업종 구성(1/3) */}
+
+
+
+
{isOperator ? '매출 구성 추이' : '참가업체 vs 바이어 매칭 추이'}
+
AI 수요예측
+
+ 우측 점선 구간은 AI 예측치입니다 (단위: 백만원 / 건).
+
+
+ {isOperator ? (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ) : (
+
+
+
+
+
+
+
+
+ )}
+
+
+
+
+
+
+
업종별 구성
+
+
+ {SECTORS.map((s) => (
+ -
+
+ {s.label}
+ {s.pct}%
+
+
+
+
+
+ ))}
+
+
+
+
+ {/* 성과 테이블(전폭) */}
+
+
+
{isOperator ? '홀·행사별 손익(P&L)' : '상위 참가사 성과'}
+ 집계 API 대기 (샘플)
+
+
+ {isOperator ? (
+
+
+
+ | 행사 |
+ 홀 |
+ 매출 |
+ 공헌이익 |
+ 마진율 |
+ 상태 |
+
+
+
+ {OPERATOR_PNL.map((r) => (
+
+ | {r.event} |
+ {r.hall} |
+ {r.revenue} |
+ {r.contribution} |
+ {r.margin} |
+ |
+
+ ))}
+
+
+ ) : (
+
+
+
+ | 업체명 |
+ 부스 |
+ 방문 수 |
+ 매칭 수 |
+ 설계 상태 |
+ 성과 |
+
+
+
+ {EXHIBITOR_PERF.map((r) => (
+
+ | {r.company} |
+ {r.booth} |
+ {r.visits.toLocaleString()} |
+ {r.matches} |
+ |
+ |
+
+ ))}
+
+
+ )}
+
+
+
+ );
+}
+
+const TOOLTIP_STYLE = {
+ fontSize: 12,
+ borderRadius: 8,
+ border: '1px solid #E4E7EC',
+ boxShadow: '0 4px 12px rgba(16,24,40,0.1)',
+} as const;
+
+function KpiCard({ kpi }: { kpi: Kpi }) {
+ return (
+
+
+ {kpi.label}
+ {kpi.ai && ✦ AI}
+
+ {kpi.value}
+ {kpi.delta && (
+
+ {kpi.deltaDir === 'down' ? '▼' : '▲'} {kpi.delta}
+
+ )}
+
+ );
+}
+
+function GradePill({ grade }: { grade: 'excellent' | 'good' | 'fair' | 'review' }) {
+ return {GRADE_LABEL[grade]};
+}
diff --git a/src/frontend/src/screens/analytics/analytics.css b/src/frontend/src/screens/analytics/analytics.css
new file mode 100644
index 0000000..e9980f4
--- /dev/null
+++ b/src/frontend/src/screens/analytics/analytics.css
@@ -0,0 +1,75 @@
+@import '../shared.css';
+
+.kx-bi {
+ flex: 1;
+ min-width: 0;
+ overflow-y: auto;
+ padding: var(--space-5);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-5);
+}
+
+.kx-bi__head {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: var(--space-4);
+ flex-wrap: wrap;
+}
+.kx-bi__title {
+ font-size: var(--fs-h1);
+ line-height: var(--lh-h1);
+ color: var(--color-neutral-900);
+}
+.kx-bi__subtitle {
+ font-size: var(--fs-body);
+ color: var(--color-neutral-500);
+ margin-top: 2px;
+}
+.kx-bi__head-actions {
+ display: flex;
+ align-items: center;
+ gap: var(--space-2);
+ flex-wrap: wrap;
+}
+
+.kx-bi__degraded-bar {
+ display: flex;
+ align-items: center;
+ gap: var(--space-3);
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+ background: var(--color-neutral-050);
+ border: var(--border-card);
+ border-radius: var(--radius-sm);
+ padding: var(--space-2) var(--space-3);
+}
+
+.kx-bi__kpis {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: var(--space-4);
+}
+
+.kx-bi__split {
+ display: grid;
+ grid-template-columns: 2fr 1fr;
+ gap: var(--space-4);
+ align-items: start;
+}
+.kx-bi__chart {
+ width: 100%;
+}
+.kx-bi__sectors {
+ align-self: stretch;
+}
+
+@media (max-width: 1100px) {
+ .kx-bi__kpis {
+ grid-template-columns: repeat(2, 1fr);
+ }
+ .kx-bi__split {
+ grid-template-columns: 1fr;
+ }
+}
diff --git a/src/frontend/src/screens/analytics/sampleAnalytics.ts b/src/frontend/src/screens/analytics/sampleAnalytics.ts
new file mode 100644
index 0000000..02eb99a
--- /dev/null
+++ b/src/frontend/src/screens/analytics/sampleAnalytics.ts
@@ -0,0 +1,123 @@
+/*
+ * 경영분석 대시보드 표시 데이터 (SCR-13 · M16 BI).
+ * ★ 경계면: M16 BI 데이터마트(FactBooking·FactSettlement·FactUtility·FactAuction·FactVisitor + Dim*)와
+ * KpiSnapshot 집계 파이프라인은 DA 후속 트랙 미구축(PLANNING §5A M16-1).
+ * 따라서 KPI·추세·RevPAD·리텐션·P&L·매칭 지표는 전부 샘플 시연이다.
+ * 원천(행사·부스·정산 레코드)은 실 API 부분 가능하나 BI 집계 API 부재 → 샘플.
+ */
+import type { FlowStatus } from '../../components/ui/Badge';
+
+export type Perspective = 'operator' | 'exhibitor';
+export type Period = 'event' | 'd90' | 'annual';
+
+export interface Kpi {
+ key: string;
+ label: string;
+ value: string;
+ delta?: string; // "+4%p"
+ deltaDir?: 'up' | 'down';
+ tone?: 'normal' | 'warn' | 'error';
+ ai?: boolean;
+}
+
+/** 매출 구성 추이 — 다계열 + 마지막 2점은 AI 예측(forecast=true). */
+export interface TrendPoint {
+ label: string;
+ rental: number; // 임대(백만)
+ utility: number; // 유틸리티(백만)
+ auction: number; // 옥션 수수료(백만)
+ forecast?: boolean;
+}
+export interface ExhibitorTrendPoint {
+ label: string;
+ exhibitors: number; // 참가업체 매칭 요청
+ buyers: number; // 바이어 매칭
+ forecast?: boolean;
+}
+
+export interface SectorRow {
+ label: string;
+ pct: number;
+}
+
+export interface PnlRow {
+ event: string;
+ hall: string;
+ revenue: string;
+ contribution: string;
+ margin: string;
+ grade: 'excellent' | 'good' | 'fair' | 'review';
+}
+export interface ExhibitorPerfRow {
+ company: string;
+ booth: string;
+ visits: number;
+ matches: number;
+ status: FlowStatus;
+ grade: 'excellent' | 'good' | 'fair' | 'review';
+}
+
+export const GRADE_LABEL: Record = {
+ excellent: '우수',
+ good: '양호',
+ fair: '보통',
+ review: '검토필요',
+};
+
+// ── 운영사 관점 ──
+export const OPERATOR_KPIS: Kpi[] = [
+ { key: 'occ', label: '홀 가동률', value: '78%', delta: '+4%p', deltaDir: 'up' },
+ { key: 'rev', label: '매출 (임대+유틸+옥션)', value: '₩1.24B', delta: '+12.5%', deltaDir: 'up' },
+ { key: 'revpad', label: '㎡당 수익 (RevPAD)', value: '₩58,200', delta: '+3.1%', deltaDir: 'up' },
+ { key: 'ret', label: '참가사 리텐션(재참가)', value: '81%', delta: '-2%p', deltaDir: 'down', tone: 'warn' },
+];
+
+export const OPERATOR_TREND: TrendPoint[] = [
+ { label: '4월', rental: 620, utility: 140, auction: 55 },
+ { label: '5월', rental: 680, utility: 155, auction: 62 },
+ { label: '6월', rental: 720, utility: 168, auction: 70 },
+ { label: '7월', rental: 790, utility: 182, auction: 78 },
+ { label: '8월', rental: 860, utility: 205, auction: 88 },
+ { label: '9월(예측)', rental: 910, utility: 220, auction: 95, forecast: true },
+ { label: '10월(예측)', rental: 965, utility: 236, auction: 102, forecast: true },
+];
+
+export const OPERATOR_PNL: PnlRow[] = [
+ { event: '스마트팩토리 코리아', hall: '홀 4·5', revenue: '₩412M', contribution: '₩168M', margin: '40.8%', grade: 'excellent' },
+ { event: '국제 헬스케어 위크', hall: '홀 7', revenue: '₩286M', contribution: '₩101M', margin: '35.3%', grade: 'good' },
+ { event: '푸드테크 엑스포', hall: '홀 3', revenue: '₩198M', contribution: '₩52M', margin: '26.3%', grade: 'fair' },
+ { event: '리빙·인테리어 페어', hall: '홀 1·2', revenue: '₩344M', contribution: '₩58M', margin: '16.9%', grade: 'review' },
+];
+
+// ── 참가업체 관점 ──
+export const EXHIBITOR_KPIS: Kpi[] = [
+ { key: 'visit', label: '총 방문 (부스)', value: '3,420', delta: '+18%', deltaDir: 'up' },
+ { key: 'stay', label: '평균 체류시간', value: '7분 20초', delta: '+42초', deltaDir: 'up' },
+ { key: 'match', label: '매칭 성공률', value: '34%', delta: '+6%p', deltaDir: 'up', ai: true },
+ { key: 'roi', label: '부스 비용 대비 리드', value: '₩38k/리드', delta: '-9%', deltaDir: 'down', tone: 'warn' },
+];
+
+export const EXHIBITOR_TREND: ExhibitorTrendPoint[] = [
+ { label: 'D-4', exhibitors: 80, buyers: 42 },
+ { label: 'D-3', exhibitors: 130, buyers: 76 },
+ { label: 'D-2', exhibitors: 205, buyers: 128 },
+ { label: 'D-1', exhibitors: 260, buyers: 172 },
+ { label: '개장일', exhibitors: 340, buyers: 240 },
+ { label: 'D+1(예측)', exhibitors: 390, buyers: 285, forecast: true },
+ { label: 'D+2(예측)', exhibitors: 430, buyers: 320, forecast: true },
+];
+
+export const EXHIBITOR_PERF: ExhibitorPerfRow[] = [
+ { company: '(주)한빛로보틱스', booth: 'A-102', visits: 512, matches: 88, status: 'approved', grade: 'excellent' },
+ { company: '누리테크놀로지', booth: 'B-201', visits: 388, matches: 61, status: 'approved', grade: 'good' },
+ { company: '대성정밀', booth: 'A-104', visits: 246, matches: 32, status: 'ai-review', grade: 'fair' },
+ { company: '세종머신', booth: 'B-205', visits: 118, matches: 9, status: 'rejected', grade: 'review' },
+];
+
+// 업종별 구성(공통) — 가로 막대.
+export const SECTORS: SectorRow[] = [
+ { label: '기술·IT', pct: 45 },
+ { label: '제조', pct: 28 },
+ { label: '헬스케어', pct: 15 },
+ { label: '유통', pct: 12 },
+];
diff --git a/src/frontend/src/screens/chartColors.ts b/src/frontend/src/screens/chartColors.ts
new file mode 100644
index 0000000..28a8159
--- /dev/null
+++ b/src/frontend/src/screens/chartColors.ts
@@ -0,0 +1,26 @@
+/*
+ * Recharts 색상 상수 — design.md §1-2 토큰을 JS 상수로 미러링.
+ * SVG 속성(fill/stroke)은 CSS 변수 var()를 신뢰할 수 없어 토큰 16진값을 직접 매핑한다.
+ * ★ 값 변경 시 반드시 styles/tokens.css(§1 권위)와 동기화할 것.
+ */
+export const CHART = {
+ primary600: '#0066B3', // 주 브랜드 블루
+ primary700: '#004C86', // 짙은 톤(hover/강조)
+ primary100: '#D9EAF7', // 활성 배경
+ primary050: '#EFF6FC',
+ aiAccent: '#6D4AFF', // AI 전용(수요예측 등)
+ aiSurface: '#F5F3FF',
+ success: '#0E8A5F',
+ warning: '#F79009', // 오버레이/차트용 앰버(§1 violation-warn)
+ error: '#D92D20',
+ slate: '#667085', // 보조 계열
+ neutral200: '#E4E7EC',
+ neutral100: '#F2F4F7',
+} as const;
+
+/** 임계 상태색 — 점유율/부하 등급별. */
+export function occupancyTone(pct: number): 'success' | 'warning' | 'error' {
+ if (pct >= 90) return 'error';
+ if (pct >= 70) return 'warning';
+ return 'success';
+}
diff --git a/src/frontend/src/screens/ops/HallOperationsPage.tsx b/src/frontend/src/screens/ops/HallOperationsPage.tsx
new file mode 100644
index 0000000..7c0b837
--- /dev/null
+++ b/src/frontend/src/screens/ops/HallOperationsPage.tsx
@@ -0,0 +1,193 @@
+import { useState } from 'react';
+import {
+ PolarAngleAxis,
+ RadialBar,
+ RadialBarChart,
+ ResponsiveContainer,
+} from 'recharts';
+import { CHART, occupancyTone } from '../chartColors';
+import {
+ HALL_CELLS,
+ HALL_GROUPS,
+ HVAC,
+ LIGHTING_ZONES,
+ PARKING_ZONES,
+ TOTAL_EST_PEOPLE,
+} from './sampleOps';
+import './ops.css';
+
+/*
+ * SCR-14 홀 현장운영 대시보드 (M14). Stitch hall_operations 이식.
+ * - 히어로: 혼잡도 히트맵(홀 셀) + 우측 HVAC·조명존 + 하단 주차 점유.
+ * ★ 경계면: 센서·IoT 전부 미연동 → 위젯 전부 샘플. 하드웨어 연동 코드 없음(§2.6).
+ */
+export function HallOperationsPage() {
+ const [mode, setMode] = useState<'live' | 'history'>('live');
+ const [group, setGroup] = useState(HALL_GROUPS[0].id);
+
+ const powerPct = Math.round((HVAC.powerLoadMw / HVAC.powerCapacityMw) * 100);
+
+ return (
+
+
+
+
+ {/* 히어로: 혼잡도 히트맵 (span 8) */}
+
+
+
실시간 혼잡도 히트맵
+
+
+ 센서 미연동 · 체크인(M10) 파생/샘플
+
+
+ {HALL_CELLS.map((c) => (
+
+ {c.label}
+ {c.level === 'busy' && 혼잡}
+ {c.estPeople.toLocaleString()}명
+
+ ))}
+
+
+
+
+
+ 총 추정 인원 {TOTAL_EST_PEOPLE.toLocaleString()}명
+
+
+
+
+ {/* 우측: HVAC + 조명존 (span 4) */}
+
+
+ {/* 하단: 주차 점유 (span 12) */}
+
+
+
주차 점유 현황
+ iparking 연계 (샘플)
+
+
+ {PARKING_ZONES.map((z) => {
+ const pct = Math.round((z.occupied / z.total) * 100);
+ const tone = occupancyTone(pct);
+ return (
+
+
+ {z.label}
+ {pct}%
+
+
+
+
+
+ {z.occupied.toLocaleString()} / {z.total.toLocaleString()}면
+
+
+ );
+ })}
+
+
+
+
+ );
+}
diff --git a/src/frontend/src/screens/ops/ops.css b/src/frontend/src/screens/ops/ops.css
new file mode 100644
index 0000000..5cba7d4
--- /dev/null
+++ b/src/frontend/src/screens/ops/ops.css
@@ -0,0 +1,317 @@
+@import '../shared.css';
+
+.kx-ops {
+ flex: 1;
+ min-width: 0;
+ overflow-y: auto;
+ padding: var(--space-5);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-5);
+}
+
+.kx-ops__head {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: var(--space-4);
+ flex-wrap: wrap;
+}
+.kx-ops__title {
+ font-size: var(--fs-h1);
+ line-height: var(--lh-h1);
+ color: var(--color-neutral-900);
+}
+.kx-ops__subtitle {
+ font-size: var(--fs-body);
+ color: var(--color-neutral-500);
+ margin-top: 2px;
+}
+
+/* 12컬럼 벤토 */
+.kx-ops__grid {
+ display: grid;
+ grid-template-columns: repeat(12, 1fr);
+ gap: var(--space-4);
+ align-items: start;
+}
+.kx-ops__heat {
+ grid-column: span 8;
+ min-height: 500px;
+ display: flex;
+ flex-direction: column;
+ position: relative;
+}
+.kx-ops__aside {
+ grid-column: span 4;
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-4);
+}
+.kx-ops__parking {
+ grid-column: span 12;
+}
+
+.kx-ops__sensor-badge {
+ position: absolute;
+ top: var(--space-4);
+ left: var(--space-4);
+ z-index: 2;
+ font-size: 11px;
+ color: var(--color-warning);
+ background: #fff4e5;
+ padding: 3px 10px;
+ border-radius: var(--radius-pill);
+}
+
+/* 히트맵 홀 셀 */
+.kx-ops__halls {
+ flex: 1;
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ gap: var(--space-3);
+ padding: var(--space-6) 0 var(--space-4);
+}
+.kx-ops__hall {
+ position: relative;
+ border-radius: var(--radius-lg);
+ padding: var(--space-4);
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ gap: var(--space-3);
+ min-height: 200px;
+ border: 1px solid transparent;
+ color: var(--color-neutral-900);
+}
+.kx-ops__hall.is-smooth {
+ background: rgba(18, 183, 106, 0.14);
+ border-color: rgba(18, 183, 106, 0.3);
+}
+.kx-ops__hall.is-moderate {
+ background: rgba(247, 144, 9, 0.16);
+ border-color: rgba(247, 144, 9, 0.32);
+}
+.kx-ops__hall.is-busy {
+ background: rgba(217, 45, 32, 0.18);
+ border-color: rgba(217, 45, 32, 0.4);
+ box-shadow: inset 0 0 0 1px rgba(217, 45, 32, 0.25);
+}
+.kx-ops__hall-label {
+ font-weight: 700;
+ font-size: var(--fs-h3);
+}
+.kx-ops__hall-tag {
+ position: absolute;
+ top: var(--space-3);
+ right: var(--space-3);
+ font-size: 11px;
+ font-weight: 700;
+ color: var(--color-white);
+ background: var(--color-error);
+ padding: 2px 8px;
+ border-radius: var(--radius-pill);
+}
+.kx-ops__hall-people {
+ font-size: var(--fs-body);
+ font-weight: 600;
+ color: var(--color-neutral-700);
+}
+
+.kx-ops__heat-foot {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--space-4);
+ border-top: var(--border-card);
+ padding-top: var(--space-3);
+ flex-wrap: wrap;
+}
+.kx-ops__legend {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ gap: var(--space-4);
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+}
+.kx-ops__legend li {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+.kx-dot {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ display: inline-block;
+}
+.kx-dot.is-smooth { background: #12b76a; }
+.kx-dot.is-moderate { background: var(--color-violation-warn); }
+.kx-dot.is-busy { background: var(--color-error); }
+.kx-ops__total {
+ font-size: var(--fs-body);
+ color: var(--color-neutral-700);
+}
+.kx-ops__total strong {
+ color: var(--color-neutral-900);
+}
+
+/* HVAC */
+.kx-ops__hvac {
+ display: flex;
+ align-items: center;
+ gap: var(--space-4);
+}
+.kx-ops__gauge {
+ position: relative;
+ width: 140px;
+ flex-shrink: 0;
+}
+.kx-ops__gauge-label {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ pointer-events: none;
+}
+.kx-ops__gauge-label strong {
+ font-size: var(--fs-h2);
+ color: var(--color-neutral-900);
+}
+.kx-ops__gauge-label span {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+}
+.kx-ops__hvac-meta {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-3);
+}
+.kx-ops__hvac-meta > div {
+ display: flex;
+ flex-direction: column;
+}
+.kx-ops__meta-k {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+}
+.kx-ops__hvac-meta strong {
+ font-size: var(--fs-h3);
+ color: var(--color-neutral-900);
+}
+.kx-ops__pill {
+ font-size: var(--fs-caption);
+ font-weight: 600;
+ padding: 2px 10px;
+ border-radius: var(--radius-pill);
+}
+.kx-ops__pill.is-ok {
+ background: #e6f4ee;
+ color: var(--color-success);
+}
+
+/* 스위치 */
+.kx-switch {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+ cursor: pointer;
+}
+.kx-switch input {
+ position: absolute;
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+.kx-switch__track {
+ width: 34px;
+ height: 20px;
+ border-radius: var(--radius-pill);
+ background: var(--color-neutral-200);
+ position: relative;
+ transition: background 0.15s ease;
+}
+.kx-switch__track::after {
+ content: '';
+ position: absolute;
+ top: 2px;
+ left: 2px;
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ background: var(--color-white);
+ transition: transform 0.15s ease;
+}
+.kx-switch input:checked + .kx-switch__track {
+ background: var(--color-primary-600);
+}
+.kx-switch input:checked + .kx-switch__track::after {
+ transform: translateX(14px);
+}
+.kx-switch input:focus-visible + .kx-switch__track {
+ outline: 2px solid var(--color-primary-600);
+ outline-offset: 2px;
+}
+
+/* 조명존 fill tone */
+.kx-barlist__fill.is-success { background: #12b76a; }
+.kx-barlist__fill.is-warning { background: var(--color-violation-warn); }
+.kx-barlist__fill.is-error { background: var(--color-error); }
+
+/* 주차 */
+.kx-ops__note {
+ font-size: 11px;
+ color: var(--color-neutral-500);
+}
+.kx-ops__zones {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: var(--space-4);
+}
+.kx-ops__zone {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-2);
+ padding: var(--space-4);
+ border: var(--border-card);
+ border-radius: var(--radius-lg);
+ background: var(--color-neutral-050);
+}
+.kx-ops__zone-top {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+}
+.kx-ops__zone-label {
+ font-size: var(--fs-body);
+ font-weight: 600;
+ color: var(--color-neutral-900);
+}
+.kx-ops__zone-pct {
+ font-size: var(--fs-h2);
+ font-weight: 700;
+}
+.kx-ops__zone-pct.is-success { color: var(--color-success); }
+.kx-ops__zone-pct.is-warning { color: var(--color-warning); }
+.kx-ops__zone-pct.is-error { color: var(--color-error); }
+.kx-ops__zone-count {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+}
+
+@media (max-width: 1200px) {
+ .kx-ops__heat { grid-column: span 12; }
+ .kx-ops__aside { grid-column: span 12; flex-direction: row; }
+ .kx-ops__aside > .kx-card { flex: 1; }
+}
+@media (max-width: 900px) {
+ .kx-ops__halls { grid-template-columns: repeat(2, 1fr); }
+ .kx-ops__zones { grid-template-columns: repeat(2, 1fr); }
+ .kx-ops__aside { flex-direction: column; }
+}
diff --git a/src/frontend/src/screens/ops/sampleOps.ts b/src/frontend/src/screens/ops/sampleOps.ts
new file mode 100644
index 0000000..a2f1cbb
--- /dev/null
+++ b/src/frontend/src/screens/ops/sampleOps.ts
@@ -0,0 +1,65 @@
+/*
+ * 홀 현장운영 대시보드 표시 데이터 (SCR-14 · M14).
+ * ★ 경계면: CCTV·혼잡 센서·HVAC/전력계·iparking·조명 IoT는 미연동
+ * (PLANNING §5A M14 "센서·IoT 연동은 킨텍스 시설 인프라 의존").
+ * 혼잡은 M10 체크인 파생, 전력은 M4 신청 부하 집계로 향후 실 데이터 가능하나 현 시점 전부 샘플.
+ * ※ 하드웨어 연동 코드 금지(§2.6). 본 화면은 표시 전용.
+ */
+export type HeatLevel = 'smooth' | 'moderate' | 'busy';
+
+export interface HallCell {
+ id: string;
+ label: string;
+ level: HeatLevel;
+ estPeople: number;
+}
+export interface ParkingZone {
+ id: string;
+ label: string;
+ occupied: number;
+ total: number;
+}
+export interface LightingZone {
+ label: string;
+ pct: number;
+}
+
+export const HALL_GROUPS = [
+ { id: 'ex1', label: '홀 1-5 (제1전시장)' },
+ { id: 'ex2', label: '홀 6-10 (제2전시장)' },
+];
+
+export const HALL_CELLS: HallCell[] = [
+ { id: 'h1', label: 'Hall 1', level: 'smooth', estPeople: 1820 },
+ { id: 'h2', label: 'Hall 2', level: 'moderate', estPeople: 3240 },
+ { id: 'h3', label: 'Hall 3', level: 'busy', estPeople: 4680 },
+ { id: 'h4', label: 'Hall 4', level: 'moderate', estPeople: 2760 },
+ { id: 'h5', label: 'Hall 5', level: 'smooth', estPeople: 1750 },
+];
+
+export const TOTAL_EST_PEOPLE = HALL_CELLS.reduce((s, c) => s + c.estPeople, 0);
+
+export const HVAC = {
+ avgTempC: 22.5,
+ powerLoadMw: 4.2,
+ powerCapacityMw: 6.0,
+ status: '최적',
+};
+
+export const LIGHTING_ZONES: LightingZone[] = [
+ { label: '전시홀', pct: 85 },
+ { label: '공용부', pct: 100 },
+];
+
+export const PARKING_ZONES: ParkingZone[] = [
+ { id: 'a', label: '존A (지하)', occupied: 1176, total: 1200 },
+ { id: 'b', label: '존B (옥외남측)', occupied: 675, total: 900 },
+ { id: 'c', label: '존C (옥외북측)', occupied: 336, total: 800 },
+ { id: 'd', label: '하역장', occupied: 24, total: 120 },
+];
+
+export const HEAT_LABEL: Record = {
+ smooth: '원활',
+ moderate: '보통',
+ busy: '혼잡',
+};
diff --git a/src/frontend/src/screens/schedule/ExhibitionSchedulePage.tsx b/src/frontend/src/screens/schedule/ExhibitionSchedulePage.tsx
new file mode 100644
index 0000000..d300caf
--- /dev/null
+++ b/src/frontend/src/screens/schedule/ExhibitionSchedulePage.tsx
@@ -0,0 +1,213 @@
+import { useMemo, useState } from 'react';
+import { useAuthStore } from '../../store/authStore';
+import { StatusBadge } from '../../components/ui/Badge';
+import { Button } from '../../components/ui/Button';
+import { EmptyState } from '../../components/ui/States';
+import {
+ CATEGORY_LABEL,
+ EVENT_DAYS,
+ HALL_UTILIZATION,
+ SAMPLE_EVENTS,
+ STATUS_LABEL,
+ type EventStatus,
+ type ScheduleEvent,
+} from './sampleSchedule';
+import './schedule.css';
+
+const MOCK = `${import.meta.env.BASE_URL}mock/organizer_dashboard`;
+const THUMBS = [`${MOCK}/img1.jpg`, `${MOCK}/img2.jpg`, `${MOCK}/img3.jpg`];
+const TODAY = new Date(2026, 6, 11); // 2026-07-11 (currentDate)
+
+/** 홀 필터 매칭 — halls 문자열("홀 4, 5"·"제2전시장 홀7")에서 "홀" 뒤 번호만 추출해 전시장 범위("1-5"/"6-10")와 대조. "제N전시장"의 N 오매칭 방지. */
+function matchesHall(halls: string, range: string): boolean {
+ if (range === 'all') return true;
+ const [lo, hi] = range.split('-').map(Number);
+ const m = halls.match(/홀\s*([\d,\s~-]+)/);
+ const nums = m ? (m[1].match(/\d+/g)?.map(Number) ?? []) : [];
+ return nums.some((n) => n >= lo && n <= hi);
+}
+
+/*
+ * SCR-15 전시 일정 관리 (M1·M6). Stitch exhibition_schedule 이식.
+ * - 좌 2/3 행사 리스트 + 우 1/3 미니 캘린더 · 홀 가동률.
+ * ★ 경계면: 행사 목록은 인증 workspaces(실 원천) 우선, 없으면 샘플. 홀 가동률·캘린더 점유는 샘플.
+ */
+export function ExhibitionSchedulePage() {
+ const workspaces = useAuthStore((s) => s.workspaces);
+ const [view, setView] = useState<'list' | 'calendar'>('list');
+ const [hall, setHall] = useState('all');
+ const [category, setCategory] = useState('all');
+ const [status, setStatus] = useState('all');
+
+ // 실 원천: 인증 workspaces → ScheduleEvent 매핑. 없으면 샘플 폴백.
+ const usingReal = workspaces.length > 0;
+ const events: ScheduleEvent[] = useMemo(() => {
+ if (!usingReal) return SAMPLE_EVENTS;
+ return workspaces.map((w, i) => ({
+ id: w.eventId,
+ title: w.eventName,
+ // ★ category/estVisitors 는 WorkspaceDto 미포함 → 샘플/기본값
+ category: 'exhibition',
+ status: (w.dday > 0 ? 'upcoming' : 'ongoing') as EventStatus,
+ period: `${w.startDate} – ${w.endDate}`,
+ halls: w.hallLabel,
+ estVisitors: '집계 대기',
+ thumbIdx: i % THUMBS.length,
+ }));
+ }, [usingReal, workspaces]);
+
+ const filtered = events.filter(
+ (e) =>
+ matchesHall(e.halls, hall) &&
+ (category === 'all' || e.category === category) &&
+ (status === 'all' || e.status === status),
+ );
+
+ return (
+
+
+
+
전시 일정
+
킨텍스 전 홀 행사 일정 관리·모니터링
+
+
+
+
+
+
+
+
+ {!usingReal &&
행사 API 대기 (샘플)}
+
+
+
+
+
+
+
+
+ {filtered.length === 0 ? (
+
+ 새 행사 생성}
+ />
+
+ ) : (
+ filtered.map((e) => (
+
+
+
+
+
{e.title}
+ {STATUS_LABEL[e.status]}
+
+
{CATEGORY_LABEL[e.category]} 전시
+
+ - ▤ {e.period}
+ - ▦ {e.halls}
+ - ◍ {e.estVisitors}
+ {e.designStatus && }
+
+
+
+
+
+
+
+ ))
+ )}
+ {view === 'calendar' && (
+
+ 캘린더 매트릭스 뷰는 M1 배정 데이터 정합 후 제공됩니다 — 현재는 목록·미니 캘린더로 확인하세요.
+
+ )}
+
+
+
+
+
+ );
+}
+
+const WD = ['일', '월', '화', '수', '목', '금', '토'];
+
+function MiniCalendar() {
+ const [cursor, setCursor] = useState(new Date(2026, 7, 1)); // 2026년 8월
+ const year = cursor.getFullYear();
+ const month = cursor.getMonth();
+ const firstDay = new Date(year, month, 1).getDay();
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
+
+ const cells: (number | null)[] = [];
+ for (let i = 0; i < firstDay; i++) cells.push(null);
+ for (let d = 1; d <= daysInMonth; d++) cells.push(d);
+
+ const isToday = (d: number) =>
+ TODAY.getFullYear() === year && TODAY.getMonth() === month && TODAY.getDate() === d;
+
+ return (
+
+
+
+ {year}년 {month + 1}월
+
+
+
+ {WD.map((w) => (
+ {w}
+ ))}
+ {cells.map((d, i) => {
+ if (d === null) return ;
+ const hasEvent = EVENT_DAYS.has(`${year}-${month + 1}-${d}`);
+ return (
+
+ {d}
+
+ );
+ })}
+
+
+ );
+}
diff --git a/src/frontend/src/screens/schedule/sampleSchedule.ts b/src/frontend/src/screens/schedule/sampleSchedule.ts
new file mode 100644
index 0000000..5ac1b65
--- /dev/null
+++ b/src/frontend/src/screens/schedule/sampleSchedule.ts
@@ -0,0 +1,99 @@
+/*
+ * 전시 일정 관리 표시 데이터 (SCR-15 · M1·M6).
+ * ★ 경계면(부분 실 + 부분 샘플):
+ * - 행사(Event) 목록·기간·배정 홀은 실 API 가능(Event 엔티티 존재).
+ * 현재는 인증 응답 workspaces(WorkspaceDto)를 실 원천으로 사용하며, 없으면 아래 샘플로 폴백한다.
+ * - 홀 가동률 집계·외부 행사일정 연동은 미구현 → 샘플. 캘린더 점유 매트릭스는 M1 배정 정합 후 실 전환.
+ */
+import type { FlowStatus } from '../../components/ui/Badge';
+
+export type EventCategory = 'exhibition' | 'culture' | 'trade' | 'tech';
+export type EventStatus = 'ongoing' | 'upcoming' | 'ended';
+
+export interface ScheduleEvent {
+ id: string;
+ title: string;
+ category: EventCategory;
+ status: EventStatus;
+ period: string; // "2026.09.05–09.08"
+ halls: string; // "홀 4, 5"
+ estVisitors: string; // "25,000명"
+ designStatus?: FlowStatus;
+ thumbIdx: number; // 로컬 mock 썸네일 인덱스
+}
+
+export const CATEGORY_LABEL: Record = {
+ exhibition: '전시',
+ culture: '문화·예술',
+ trade: '무역·산업',
+ tech: '기술',
+};
+export const STATUS_LABEL: Record = {
+ ongoing: '진행중',
+ upcoming: '예정',
+ ended: '종료',
+};
+
+export const SAMPLE_EVENTS: ScheduleEvent[] = [
+ {
+ id: 'smf2026',
+ title: '스마트팩토리 코리아',
+ category: 'trade',
+ status: 'ongoing',
+ period: '2026.09.05–09.08',
+ halls: '홀 4, 5',
+ estVisitors: '25,000명',
+ designStatus: 'building',
+ thumbIdx: 0,
+ },
+ {
+ id: 'health2026',
+ title: '국제 헬스케어 위크',
+ category: 'exhibition',
+ status: 'upcoming',
+ period: '2026.09.22–09.25',
+ halls: '홀 7',
+ estVisitors: '18,000명',
+ designStatus: 'submitted',
+ thumbIdx: 1,
+ },
+ {
+ id: 'foodtech2026',
+ title: '푸드테크 엑스포',
+ category: 'tech',
+ status: 'upcoming',
+ period: '2026.10.10–10.13',
+ halls: '홀 3',
+ estVisitors: '12,000명',
+ designStatus: 'draft',
+ thumbIdx: 2,
+ },
+ {
+ id: 'living2026',
+ title: '리빙·인테리어 페어',
+ category: 'culture',
+ status: 'ended',
+ period: '2026.08.14–08.17',
+ halls: '홀 1, 2',
+ estVisitors: '30,000명',
+ designStatus: 'inspected',
+ thumbIdx: 0,
+ },
+];
+
+export interface HallUtilRow {
+ label: string;
+ pct: number;
+}
+export const HALL_UTILIZATION: HallUtilRow[] = [
+ { label: '홀 1-3', pct: 85 },
+ { label: '홀 4-5', pct: 40 },
+ { label: '홀 6-8', pct: 62 },
+ { label: '홀 9-10', pct: 18 },
+];
+
+// 미니 캘린더 하이라이트 날짜(샘플) — key: 'YYYY-M-D'
+export const EVENT_DAYS = new Set([
+ '2026-8-14', '2026-8-15', '2026-8-16', '2026-8-17',
+ '2026-9-5', '2026-9-6', '2026-9-7', '2026-9-8',
+]);
diff --git a/src/frontend/src/screens/schedule/schedule.css b/src/frontend/src/screens/schedule/schedule.css
new file mode 100644
index 0000000..a39cecd
--- /dev/null
+++ b/src/frontend/src/screens/schedule/schedule.css
@@ -0,0 +1,221 @@
+@import '../shared.css';
+
+.kx-sched {
+ flex: 1;
+ min-width: 0;
+ overflow-y: auto;
+ padding: var(--space-5);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-5);
+}
+
+.kx-sched__title {
+ font-size: var(--fs-h1);
+ line-height: var(--lh-h1);
+ color: var(--color-neutral-900);
+}
+.kx-sched__subtitle {
+ font-size: var(--fs-body);
+ color: var(--color-neutral-500);
+ margin-top: 2px;
+}
+
+.kx-sched__filters {
+ display: flex;
+ align-items: center;
+ gap: var(--space-2);
+ flex-wrap: wrap;
+}
+.kx-sched__filter-spacer {
+ flex: 1;
+}
+
+.kx-sched__split {
+ display: grid;
+ grid-template-columns: 2fr 1fr;
+ gap: var(--space-4);
+ align-items: start;
+}
+.kx-sched__list {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-4);
+}
+.kx-sched__calnote {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+ padding: var(--space-3);
+ background: var(--color-neutral-050);
+ border: var(--border-card);
+ border-radius: var(--radius-sm);
+}
+.kx-sched__aside {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-4);
+}
+
+/* 행사 카드 */
+.kx-evcard {
+ display: flex;
+ gap: var(--space-4);
+ border: var(--border-card);
+ border-radius: var(--radius-lg);
+ background: var(--color-white);
+ overflow: hidden;
+}
+.kx-evcard__poster {
+ width: 160px;
+ flex-shrink: 0;
+ background-size: cover;
+ background-position: center;
+ background-color: var(--color-neutral-100);
+}
+.kx-evcard__body {
+ flex: 1;
+ min-width: 0;
+ padding: var(--space-4);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-2);
+}
+.kx-evcard__top {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--space-3);
+}
+.kx-evcard__title {
+ font-size: var(--fs-h3);
+ color: var(--color-neutral-900);
+}
+.kx-evcard__cat {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+}
+.kx-evcard__meta {
+ list-style: none;
+ margin: var(--space-1) 0;
+ padding: 0;
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--space-2) var(--space-4);
+ font-size: var(--fs-body);
+ color: var(--color-neutral-700);
+}
+.kx-evcard__meta li {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+.kx-evcard__actions {
+ display: flex;
+ gap: var(--space-2);
+ margin-top: auto;
+}
+
+/* 행사 상태 pill */
+.kx-evstatus {
+ font-size: var(--fs-caption);
+ font-weight: 600;
+ padding: 2px 10px;
+ border-radius: var(--radius-pill);
+ white-space: nowrap;
+}
+.kx-evstatus.is-ongoing {
+ background: #e6f4ee;
+ color: var(--color-success);
+}
+.kx-evstatus.is-upcoming {
+ background: #fff4e5;
+ color: var(--color-warning);
+}
+.kx-evstatus.is-ended {
+ background: var(--color-neutral-100);
+ color: var(--color-neutral-500);
+}
+
+/* 미니 캘린더 */
+.kx-cal__head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: var(--space-3);
+ font-size: var(--fs-body);
+ color: var(--color-neutral-900);
+}
+.kx-cal__nav {
+ width: 28px;
+ height: 28px;
+ border: var(--border-card);
+ border-radius: var(--radius-sm);
+ background: var(--color-white);
+ color: var(--color-neutral-700);
+ font-size: 16px;
+ cursor: pointer;
+}
+.kx-cal__nav:hover {
+ background: var(--color-neutral-050);
+}
+.kx-cal__grid {
+ display: grid;
+ grid-template-columns: repeat(7, 1fr);
+ gap: 4px;
+}
+.kx-cal__wd {
+ text-align: center;
+ font-size: 11px;
+ color: var(--color-neutral-500);
+ padding-bottom: 4px;
+}
+.kx-cal__cell {
+ aspect-ratio: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-700);
+ border-radius: var(--radius-sm);
+ position: relative;
+}
+.kx-cal__cell.is-empty {
+ visibility: hidden;
+}
+.kx-cal__cell.has-event {
+ background: var(--color-primary-050);
+ color: var(--color-primary-700);
+ font-weight: 600;
+}
+.kx-cal__cell.has-event::after {
+ content: '';
+ position: absolute;
+ bottom: 3px;
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: var(--color-primary-600);
+}
+.kx-cal__cell.is-today {
+ background: var(--color-primary-600);
+ color: var(--color-white);
+ font-weight: 700;
+}
+.kx-cal__cell.is-today.has-event::after {
+ background: var(--color-white);
+}
+
+@media (max-width: 1100px) {
+ .kx-sched__split {
+ grid-template-columns: 1fr;
+ }
+}
+@media (max-width: 620px) {
+ .kx-evcard {
+ flex-direction: column;
+ }
+ .kx-evcard__poster {
+ width: 100%;
+ height: 120px;
+ }
+}
diff --git a/src/frontend/src/screens/shared.css b/src/frontend/src/screens/shared.css
new file mode 100644
index 0000000..695744a
--- /dev/null
+++ b/src/frontend/src/screens/shared.css
@@ -0,0 +1,205 @@
+/*
+ * v2.0 확장 화면(SCR-13~17) 공통 프리미티브.
+ * design.md §1 토큰만 참조. 각 화면 CSS가 @import 로 선반영한다.
+ */
+
+/* 스크롤 가능한 페이지 루트 — kx-shell__content(overflow:hidden, flex) 내부에서 자체 스크롤. */
+.kx-page {
+ flex: 1;
+ min-width: 0;
+ overflow-y: auto;
+ padding: var(--space-5);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-5);
+}
+
+/* 카드 */
+.kx-card {
+ border: var(--border-card);
+ border-radius: var(--radius-lg);
+ background: var(--color-white);
+ padding: var(--space-4);
+}
+.kx-card__head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--space-3);
+ margin-bottom: var(--space-3);
+}
+.kx-card__head h2 {
+ font-size: var(--fs-h3);
+ color: var(--color-neutral-900);
+}
+.kx-card__hint {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+ margin: -4px 0 var(--space-3);
+}
+
+/* 세그먼트 토글 */
+.kx-seg {
+ display: inline-flex;
+ padding: 3px;
+ background: var(--color-neutral-100);
+ border-radius: var(--radius-sm);
+ gap: 2px;
+}
+.kx-seg__btn {
+ padding: 6px 14px;
+ border: none;
+ background: transparent;
+ border-radius: 3px;
+ font-size: var(--fs-body);
+ font-weight: 600;
+ color: var(--color-neutral-500);
+ cursor: pointer;
+}
+.kx-seg__btn.is-active {
+ background: var(--color-white);
+ color: var(--color-primary-700);
+ box-shadow: 0 1px 2px rgba(16, 24, 40, 0.08);
+}
+
+/* 셀렉트 */
+.kx-select {
+ height: 36px;
+ padding: 0 var(--space-3);
+ border: var(--border-card);
+ border-radius: var(--radius-sm);
+ background: var(--color-white);
+ font-size: var(--fs-body);
+ color: var(--color-neutral-700);
+}
+
+/* KPI 카드(공통) */
+.kx-kpi {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-1);
+ padding: var(--space-4);
+ border: var(--border-card);
+ border-radius: var(--radius-lg);
+ background: var(--color-white);
+}
+.kx-kpi__label {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+}
+.kx-kpi__ai {
+ color: var(--color-ai-accent);
+ font-weight: 700;
+ font-size: 11px;
+}
+.kx-kpi__value {
+ font-size: var(--fs-display);
+ line-height: var(--lh-display);
+ font-weight: 700;
+ color: var(--color-neutral-900);
+}
+.kx-kpi--warn {
+ border-color: var(--color-violation-warn);
+}
+.kx-kpi--error .kx-kpi__value {
+ color: var(--color-error);
+}
+
+/* 델타 칩 */
+.kx-delta {
+ align-self: flex-start;
+ font-size: var(--fs-caption);
+ font-weight: 700;
+ padding: 1px 8px;
+ border-radius: var(--radius-pill);
+}
+.kx-delta--up {
+ color: var(--color-success);
+ background: #e6f4ee;
+}
+.kx-delta--down {
+ color: var(--color-error);
+ background: #fef3f2;
+}
+
+/* degraded 배지 */
+.kx-bi__degraded {
+ font-size: 11px;
+ color: var(--color-warning);
+ background: #fff4e5;
+ padding: 2px 8px;
+ border-radius: var(--radius-pill);
+ white-space: nowrap;
+}
+
+/* 테이블 확장 */
+.kx-table-scroll {
+ overflow-x: auto;
+}
+.kx-table--zebra tbody tr:nth-child(even) {
+ background: var(--zebra);
+}
+.kx-table thead th {
+ position: sticky;
+ top: 0;
+}
+.kx-num {
+ text-align: right;
+}
+
+/* 가로 막대 리스트 */
+.kx-barlist {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-4);
+}
+.kx-barlist__top {
+ display: flex;
+ justify-content: space-between;
+ font-size: var(--fs-body);
+ color: var(--color-neutral-700);
+ margin-bottom: 6px;
+}
+.kx-barlist__track {
+ height: 8px;
+ border-radius: var(--radius-pill);
+ background: var(--color-neutral-100);
+ overflow: hidden;
+}
+.kx-barlist__fill {
+ display: block;
+ height: 100%;
+ border-radius: var(--radius-pill);
+ background: var(--color-primary-600);
+}
+
+/* 성과 배지 */
+.kx-grade {
+ display: inline-block;
+ font-size: var(--fs-caption);
+ font-weight: 600;
+ padding: 2px 10px;
+ border-radius: var(--radius-pill);
+}
+.kx-grade--excellent {
+ background: #e6f4ee;
+ color: var(--color-success);
+}
+.kx-grade--good {
+ background: var(--color-primary-050);
+ color: var(--color-primary-700);
+}
+.kx-grade--fair {
+ background: #fff4e5;
+ color: var(--color-warning);
+}
+.kx-grade--review {
+ background: #fef3f2;
+ color: var(--color-error);
+}
diff --git a/src/frontend/src/screens/styleguide/ComponentGuidePage.tsx b/src/frontend/src/screens/styleguide/ComponentGuidePage.tsx
new file mode 100644
index 0000000..3ca5248
--- /dev/null
+++ b/src/frontend/src/screens/styleguide/ComponentGuidePage.tsx
@@ -0,0 +1,198 @@
+import { AiImage } from '../../components/ui/AiImage';
+import { AiLabel, DdayChip, RoleBadge, StatusBadge, type FlowStatus } from '../../components/ui/Badge';
+import { Button } from '../../components/ui/Button';
+import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
+import './styleguide.css';
+
+/*
+ * SCR-17 컴포넌트 가이드 (§1 실증 스타일가이드 / 스토리북 성격).
+ * 내부 전용(/_styleguide) — 제품 내비 비노출. 색·치수 권위는 design.md §1(tokens.css).
+ * 실 데이터·API 없음(정적 참조). 기존 공통 컴포넌트를 실물 렌더한다.
+ */
+const STATUS_FLOW: FlowStatus[] = [
+ 'draft', 'submitted', 'ai-review', 'approved', 'rejected', 'building', 'inspected',
+];
+
+const SWATCHES = [
+ { name: 'KINTEX Blue', varName: '--color-primary-600', hex: '#0066B3' },
+ { name: 'Primary 700', varName: '--color-primary-700', hex: '#004C86' },
+ { name: 'AI Accent', varName: '--color-ai-accent', hex: '#6D4AFF' },
+ { name: 'Success', varName: '--color-success', hex: '#0E8A5F' },
+ { name: 'Error', varName: '--color-error', hex: '#D92D20' },
+ { name: 'Warning', varName: '--color-warning', hex: '#B45309' },
+ { name: 'Neutral 900', varName: '--color-neutral-900', hex: '#101828' },
+ { name: 'Neutral 200', varName: '--color-neutral-200', hex: '#E4E7EC' },
+];
+
+const MOCK = `${import.meta.env.BASE_URL}mock/organizer_dashboard/img1.jpg`;
+
+export function ComponentGuidePage() {
+ return (
+
+
+
+
+ {/* 1. 타이포 & 컬러 */}
+
+ 타이포그래피 & 컬러
+
+
전시공간 최적화 엔진
+
도면 분석 보고서
+
부스 배치 시뮬레이션
+
+ 본문 텍스트 — 참가업체 설계 스펙과 규정 검증 결과를 정밀하게 표시합니다. Pretendard 14px.
+
+
+
+ {SWATCHES.map((s) => (
+
+
+ {s.name}
+ {s.hex}
+
+ ))}
+
+
+
+ {/* 2. AI 전용 요소 */}
+
+ AI 전용 요소
+
+
+
+ 📍 피난 통로 차단
+ 📍 바닥하중 초과
+
+
+
+ {/* 3. 버튼 & 액션 */}
+
+ 버튼 & 액션
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* 4. 상태 배지 & 칩 */}
+
+ 상태 배지 & 칩
+
+ {STATUS_FLOW.map((s) => (
+
+ ))}
+
+
+
+
+
+
+
+ Hall 1A
+ High Traffic
+
+
+
+ {/* 5. 데이터 시각화 (범례·게이지 — 실제는 Recharts로 대체) */}
+
+ 데이터 시각화
+ 차트 구현은 Recharts 사용 (SCR-13·14·16). 여기서는 토큰·범례만 실증.
+
+
+ 전시장 점유율
+ 78% / 임계치 85%
+
+
+
+
+
+
+
+
+ {/* 6. 폼 요소 */}
+
+
+ {/* 7. 피드백 & 오버레이 */}
+
+ 피드백 & 오버레이
+ 데이터가 저장되었습니다
+ ⚠ 소방법 위반 구역 3곳
+
+
+
+
+
+
+
+
+
+ {}} />
+
+
+
+
+
+ );
+}
diff --git a/src/frontend/src/screens/styleguide/styleguide.css b/src/frontend/src/screens/styleguide/styleguide.css
new file mode 100644
index 0000000..d70db58
--- /dev/null
+++ b/src/frontend/src/screens/styleguide/styleguide.css
@@ -0,0 +1,285 @@
+@import '../shared.css';
+
+.kx-sg {
+ flex: 1;
+ min-width: 0;
+ overflow-y: auto;
+ padding: var(--space-5);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-5);
+ background: var(--color-neutral-050);
+}
+
+.kx-sg__head {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: var(--space-4);
+ flex-wrap: wrap;
+}
+.kx-sg__eyebrow {
+ font-size: var(--fs-caption);
+ font-weight: 700;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ color: var(--color-primary-600);
+}
+.kx-sg__title {
+ font-size: var(--fs-display);
+ line-height: var(--lh-display);
+ color: var(--color-neutral-900);
+}
+.kx-sg__desc {
+ font-size: var(--fs-body);
+ color: var(--color-neutral-500);
+ margin-top: 4px;
+ max-width: 640px;
+}
+.kx-sg__ver {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+ background: var(--color-white);
+ border: var(--border-card);
+ border-radius: var(--radius-pill);
+ padding: 4px 12px;
+}
+
+.kx-sg__grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: var(--space-4);
+ align-items: start;
+}
+
+.kx-sg-card {
+ position: relative;
+ background: var(--color-white);
+ border: var(--border-card);
+ border-radius: var(--radius-lg);
+ padding: var(--space-5);
+ padding-left: var(--space-5);
+ overflow: hidden;
+}
+.kx-sg-card::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ width: 4px;
+}
+.kx-sg-card[data-accent='primary']::before { background: var(--color-primary-600); }
+.kx-sg-card[data-accent='ai']::before { background: var(--color-ai-accent); }
+.kx-sg-card[data-accent='success']::before { background: var(--color-success); }
+.kx-sg-card__title {
+ font-size: var(--fs-h3);
+ color: var(--color-neutral-900);
+ margin-bottom: var(--space-4);
+}
+.kx-sg-card__note {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+ margin: -8px 0 var(--space-4);
+}
+
+/* 타이포 */
+.kx-sg__type {
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-2);
+ padding-bottom: var(--space-4);
+ border-bottom: var(--border-card);
+ margin-bottom: var(--space-4);
+}
+.kx-sg__t-display { font-size: var(--fs-display); line-height: var(--lh-display); font-weight: 700; color: var(--color-neutral-900); }
+.kx-sg__t-headline { font-size: var(--fs-h1); line-height: var(--lh-h1); font-weight: 700; color: var(--color-neutral-900); }
+.kx-sg__t-title { font-size: var(--fs-h3); font-weight: 600; color: var(--color-neutral-700); }
+.kx-sg__t-body { font-size: var(--fs-body); color: var(--color-neutral-700); }
+
+.kx-sg__swatches {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: var(--space-3);
+}
+.kx-sg__swatch {
+ display: flex;
+ align-items: center;
+ gap: var(--space-2);
+}
+.kx-sg__swatch-chip {
+ width: 28px;
+ height: 28px;
+ border-radius: var(--radius-sm);
+ border: 1px solid rgba(16, 24, 40, 0.08);
+ flex-shrink: 0;
+}
+.kx-sg__swatch-name {
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-700);
+ flex: 1;
+}
+.kx-sg__swatch-hex {
+ font-size: 11px;
+ color: var(--color-neutral-500);
+}
+
+/* AI 요소 */
+.kx-sg__ai-row,
+.kx-sg__btn-row,
+.kx-sg__chip-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--space-2);
+ align-items: center;
+ margin-bottom: var(--space-4);
+}
+.kx-sg__aiimg {
+ max-width: 320px;
+ margin-bottom: var(--space-4);
+}
+.kx-sg__violations {
+ display: flex;
+ gap: var(--space-3);
+}
+.kx-sg__viol {
+ font-size: var(--fs-caption);
+ font-weight: 600;
+ color: var(--color-error);
+ background: #fef3f2;
+ border-radius: var(--radius-sm);
+ padding: 4px 10px;
+}
+
+.kx-sg__icon-btn {
+ width: 36px;
+ height: 36px;
+ border: var(--border-card);
+ border-radius: var(--radius-sm);
+ background: var(--color-white);
+ color: var(--color-neutral-700);
+ cursor: pointer;
+}
+.kx-sg__icon-btn:hover {
+ background: var(--color-neutral-050);
+}
+
+/* 게이지·범례 */
+.kx-sg__gauge {
+ margin-bottom: var(--space-4);
+}
+.kx-sg__legend {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ gap: var(--space-4);
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+}
+.kx-sg__legend li {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+.kx-dot {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ display: inline-block;
+}
+.kx-dot.is-smooth { background: #12b76a; }
+.kx-dot.is-moderate { background: var(--color-violation-warn); }
+.kx-dot.is-busy { background: var(--color-error); }
+.kx-barlist__fill.is-warning { background: var(--color-violation-warn); }
+
+/* 폼 */
+.kx-sg__form {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: var(--space-4);
+}
+.kx-sg__field {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ font-size: var(--fs-caption);
+ color: var(--color-neutral-500);
+}
+.kx-sg__input {
+ height: 36px;
+ padding: 0 var(--space-3);
+ border: var(--border-card);
+ border-radius: var(--radius-sm);
+ font-size: var(--fs-body);
+ color: var(--color-neutral-900);
+}
+.kx-sg__input:focus {
+ outline: none;
+ border-color: var(--color-primary-600);
+ box-shadow: 0 0 0 3px rgba(0, 102, 179, 0.15);
+}
+.kx-sg__input.is-error {
+ border-color: var(--color-error);
+}
+.kx-sg__err-msg {
+ color: var(--color-error);
+ font-style: normal;
+ font-size: 11px;
+}
+.kx-sg__check-row {
+ grid-column: 1 / -1;
+ display: flex;
+ gap: var(--space-4);
+}
+.kx-sg__check {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ font-size: var(--fs-body);
+ color: var(--color-neutral-700);
+}
+
+/* 피드백 */
+.kx-sg__toast {
+ display: inline-block;
+ background: var(--color-neutral-900);
+ color: var(--color-white);
+ font-size: var(--fs-body);
+ padding: 10px var(--space-4);
+ border-radius: var(--radius-sm);
+ margin-bottom: var(--space-3);
+}
+.kx-sg__alert {
+ background: #fef3f2;
+ color: var(--color-error);
+ font-size: var(--fs-body);
+ font-weight: 600;
+ padding: 10px var(--space-4);
+ border-radius: var(--radius-sm);
+ border: 1px solid rgba(217, 45, 32, 0.3);
+ margin-bottom: var(--space-4);
+}
+.kx-sg__states {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: var(--space-3);
+}
+.kx-sg__state-box {
+ border: var(--border-card);
+ border-radius: var(--radius-sm);
+ padding: var(--space-3);
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-2);
+ min-height: 120px;
+ justify-content: center;
+}
+
+@media (max-width: 1000px) {
+ .kx-sg__grid,
+ .kx-sg__form,
+ .kx-sg__states {
+ grid-template-columns: 1fr;
+ }
+}
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_ai_bot/code.html b/stitch_kintex_ai_system_architect/_icons/icon_ai_bot/code.html
new file mode 100644
index 0000000..abd30ed
--- /dev/null
+++ b/stitch_kintex_ai_system_architect/_icons/icon_ai_bot/code.html
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_ai_bot/screen.png b/stitch_kintex_ai_system_architect/_icons/icon_ai_bot/screen.png
new file mode 100644
index 0000000..0fdd0a0
Binary files /dev/null and b/stitch_kintex_ai_system_architect/_icons/icon_ai_bot/screen.png differ
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_analytics/code.html b/stitch_kintex_ai_system_architect/_icons/icon_analytics/code.html
new file mode 100644
index 0000000..e207818
--- /dev/null
+++ b/stitch_kintex_ai_system_architect/_icons/icon_analytics/code.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_analytics/screen.png b/stitch_kintex_ai_system_architect/_icons/icon_analytics/screen.png
new file mode 100644
index 0000000..6e0f742
Binary files /dev/null and b/stitch_kintex_ai_system_architect/_icons/icon_analytics/screen.png differ
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_calendar/code.html b/stitch_kintex_ai_system_architect/_icons/icon_calendar/code.html
new file mode 100644
index 0000000..19ce073
--- /dev/null
+++ b/stitch_kintex_ai_system_architect/_icons/icon_calendar/code.html
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_calendar/screen.png b/stitch_kintex_ai_system_architect/_icons/icon_calendar/screen.png
new file mode 100644
index 0000000..0483f7b
Binary files /dev/null and b/stitch_kintex_ai_system_architect/_icons/icon_calendar/screen.png differ
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_dashboard/code.html b/stitch_kintex_ai_system_architect/_icons/icon_dashboard/code.html
new file mode 100644
index 0000000..f7a42c4
--- /dev/null
+++ b/stitch_kintex_ai_system_architect/_icons/icon_dashboard/code.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_dashboard/screen.png b/stitch_kintex_ai_system_architect/_icons/icon_dashboard/screen.png
new file mode 100644
index 0000000..f0f6afb
Binary files /dev/null and b/stitch_kintex_ai_system_architect/_icons/icon_dashboard/screen.png differ
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_menu/code.html b/stitch_kintex_ai_system_architect/_icons/icon_menu/code.html
new file mode 100644
index 0000000..c7e5f11
--- /dev/null
+++ b/stitch_kintex_ai_system_architect/_icons/icon_menu/code.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_menu/screen.png b/stitch_kintex_ai_system_architect/_icons/icon_menu/screen.png
new file mode 100644
index 0000000..a97c444
Binary files /dev/null and b/stitch_kintex_ai_system_architect/_icons/icon_menu/screen.png differ
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_operations/code.html b/stitch_kintex_ai_system_architect/_icons/icon_operations/code.html
new file mode 100644
index 0000000..b60c18a
--- /dev/null
+++ b/stitch_kintex_ai_system_architect/_icons/icon_operations/code.html
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_operations/screen.png b/stitch_kintex_ai_system_architect/_icons/icon_operations/screen.png
new file mode 100644
index 0000000..8df28de
Binary files /dev/null and b/stitch_kintex_ai_system_architect/_icons/icon_operations/screen.png differ
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_search/code.html b/stitch_kintex_ai_system_architect/_icons/icon_search/code.html
new file mode 100644
index 0000000..eb61ffa
--- /dev/null
+++ b/stitch_kintex_ai_system_architect/_icons/icon_search/code.html
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/stitch_kintex_ai_system_architect/_icons/icon_search/screen.png b/stitch_kintex_ai_system_architect/_icons/icon_search/screen.png
new file mode 100644
index 0000000..482c155
Binary files /dev/null and b/stitch_kintex_ai_system_architect/_icons/icon_search/screen.png differ
diff --git a/stitch_kintex_ai_system_architect/admin_dashboard_kintex_ai_system/code.html b/stitch_kintex_ai_system_architect/admin_dashboard_kintex_ai_system/code.html
index 7dbfd12..949af3a 100644
--- a/stitch_kintex_ai_system_architect/admin_dashboard_kintex_ai_system/code.html
+++ b/stitch_kintex_ai_system_architect/admin_dashboard_kintex_ai_system/code.html
@@ -1,13 +1,11 @@
-
+```html
-
-
-
+
+
KINTEX AI CMS - Dashboard
-
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
D-31
+
+
+

+
+
+
+
+
+
+
+
+
+
System Reference
+
Component Guide
+
+ KINTEX AI 디자인 시스템 v1.0. 본 가이드는 고도의 신뢰성과 정밀한 정보 처리가 필요한 B2B 전시 환경을 위해 설계되었습니다.
+
+
+
+LATEST STABLE v1.0.4
+
+
+
+
+
+
+
Typography & Colors
+
+
+
+
+
+Pretendard Type Scale
+
+
+
+
Display Large (36px)
+
전시공간 최적화 엔진
+
+
+
Headline Medium (24px)
+
도면 분석 보고서
+
+
+
Title Small (18px)
+
신규 부스 배치 시뮬레이션
+
+
+
Body Base (14px)
+
전시 관리자는 실시간으로 변화하는 도면 데이터를 분석하여 최적의 동선을 설계합니다.
+
+
+
+
+
+
+Primary Color Palette
+
+
+
+
+
+
+
+
+
AI Specific Elements
+
+
+
+
+auto_awesome
+AI Drafted Component
+
+
+
+
+AI GENERATEDAI GENERATEDAI GENERATED
+AI GENERATEDAI GENERATEDAI GENERATED
+
+
워터마크 샘플 영역
+
+
+
+
Violation Flag Pins (Safety)
+
+
+location_on
+Fire Exit Block
+
+
+warning
+Overload
+
+
+
+
+
+
+smart_toy
+
+
+
+
+
+
Buttons & Actions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Status Badges & Chips
+
+
+
+
Lifecycle Status
+
+작성중
+제출됨
+AI검토
+승인
+반려
+
+
+시공중
+검수완료
+
+
+
+
Contextual Chips
+
+
+alarm D-3
+
+
+event 10/24
+
+Hall 1A
+High Traffic
+
+
+
+
+
+
+
+
Data Visualization Components
+
+
+
+
+
+전시장 점유율
+78%
+
+
+
+0%
+임계치 85%
+100%
+
+
+
+
+
+
+
방문객 추이 (Weekly)
+
+
+MonWedSun
+
+
+
+
+
+
+
+
Form Elements
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
올바른 위치 정보를 입력하세요.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Feedback & Overlays
+
+
+
+
+
+check_circle
+데이터가 성공적으로 저장되었습니다.
+
+
+
+
+
+
error
+
+
중요 알림
+
현재 설계된 도면에 소방법 위반 구역이 3곳 발견되었습니다. 수정을 권장합니다.
+
+
+
+
+
+
변경사항 적용
+
수정된 레이아웃을 서버에 동기화하시겠습니까? 이 작업은 되돌릴 수 없습니다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/stitch_kintex_ai_system_architect/component_guide_updated_kintex_ai_system/code.html b/stitch_kintex_ai_system_architect/component_guide_updated_kintex_ai_system/code.html
new file mode 100644
index 0000000..0c17614
--- /dev/null
+++ b/stitch_kintex_ai_system_architect/component_guide_updated_kintex_ai_system/code.html
@@ -0,0 +1,616 @@
+
+
+
+KINTEX AI - UI Library
+
+
+
+
+
+
+
+
+
+
+
+
+
+
D-31
+
+
+

+
+
+
+
+
+
+
+
+
+
System Reference
+
Component Guide
+
+ KINTEX AI 디자인 시스템 v1.0. 본 가이드는 고도의 신뢰성과 정밀한 정보 처리가 필요한 B2B 전시 환경을 위해 설계되었습니다.
+
+
+
+LATEST STABLE v1.0.4
+
+
+
+
+
+
+
Typography & Colors
+
+
+
+
+
+Pretendard Type Scale
+
+
+
+
Display Large (36px)
+
전시공간 최적화 엔진
+
+
+
Headline Medium (24px)
+
도면 분석 보고서
+
+
+
Title Small (18px)
+
신규 부스 배치 시뮬레이션
+
+
+
Body Base (14px)
+
전시 관리자는 실시간으로 변화하는 도면 데이터를 분석하여 최적의 동선을 설계합니다.
+
+
+
+
+
+
+Primary Color Palette
+
+
+
+
+
+
+
+
+
AI Specific Elements
+
+
+
+
+

+
AI Drafted Component
+
+
+
+AI GENERATEDAI GENERATEDAI GENERATED
+AI GENERATEDAI GENERATEDAI GENERATED
+
+
워터마크 샘플 영역
+
+
+
+
Violation Flag Pins (Safety)
+
+
+location_on
+Fire Exit Block
+
+
+warning
+Overload
+
+
+
+
+
+
+
https://lh3.googleusercontent.com/aida/AP1WRLu1SFz3uW8s6iC8BUAS9XvAFoM_7LQZUzR-UgorcHCSIZ_uRCF-ZTLQnQbNUG13WdRaQDX_3m0ewu6jxJ2Ie-gQvwFXyYdy3ZIxhkl0hJ2VGRZF6Iul1GgmSKzO5x92HASTCa0m0XzXjctyxy5aRgxOTOxhzl-Qz9P5jTlRzXngIWh6bCNZdaVEIxd9H6a2fDdToHYg0gowaU93SV2P5YbT0-8ShD0eeNiQEFHXn4HcsQUCrsiacEeGDZY
+
+
+
+
+
+
Buttons & Actions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Status Badges & Chips
+
+
+
+
Lifecycle Status
+
+작성중
+제출됨
+AI검토
+승인
+반려
+
+
+시공중
+검수완료
+
+
+
+
Contextual Chips
+
+
+
D-3
+
+
+
10/24
+
+
Hall 1A
+
High Traffic
+
+
+
+
+
+
+
+
System Assets Library (Custom SVG)
+
+
+
+

+
Dashboard
+
+
+

+
Calendar
+
+
+

+
Operations
+
+
+

+
Analytics
+
+
+

+
Search
+
+
+

+
Menu
+
+
Friendly AI Bot
+
+
+
+
+
+
Data Visualization Components
+
+
+
+
+
+전시장 점유율
+78%
+
+
+
+0%
+임계치 85%
+100%
+
+
+
+
+
+
+
+
방문객 추이 (Weekly)
+
https://lh3.googleusercontent.com/aida/AP1WRLujD1FMRHChfM_aVKt2cd12chhcnm31L8Ks2EAzo-_FQ1_RV3zmYa4WUlSJ67wYexda4SpJU88Y5L0HdiYx6fLuKFdsDKjKWm1SmTq4PIP2tx1Nys-Txdlq4Wc1keg1GKsgrxNY68bHBEhurr-0NorgLbpp032gBkj_vE345bYKJwSr5MEnipvo_1P7iE9cXEBybLmdLLYK6vM1nB7dbmVt9_NHG3NQgK7wcPfIaNBrnXrEqtZeckWX3v8
+
+
+
+MonWedSun
+
+
+
+
+
+
+
+
Form Elements
+
+
+
+
+
+
+
+https://lh3.googleusercontent.com/aida/AP1WRLvR8KDDPFgH9vKk_aFJ_lA5WCSRmrDnPhJH5rSjuWilOAI5PMDe5z2hRnRLQhSn7_712ig52lC61Bb_R8bUkkbqNGZPv3dvykD_Oky9hXWygGnc1ybvaI9TcbT1Yw4Bd2JySNFbit4ho4113ql2BsDvpvJ2ZN64zJqv5GowDs0mdnDyFTwPWmGEKEPr3MigJ4LAaeegtd0fEG_pZWtGpsGSNPVdj4r_TbmkKSxdvmZG_kh-ujSkrXGZzkQ
+
+
+
+
+
+
+
+
+
+
올바른 위치 정보를 입력하세요.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Feedback & Overlays
+
+
+
+
+
+check_circle
+데이터가 성공적으로 저장되었습니다.
+
+
+
+
+
+
error
+
+
중요 알림
+
현재 설계된 도면에 소방법 위반 구역이 3곳 발견되었습니다. 수정을 권장합니다.
+
+
+
+
+
+
변경사항 적용
+
수정된 레이아웃을 서버에 동기화하시겠습니까? 이 작업은 되돌릴 수 없습니다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/stitch_kintex_ai_system_architect/exhibition_schedule_kintex_ai_system/code.html b/stitch_kintex_ai_system_architect/exhibition_schedule_kintex_ai_system/code.html
index e33255f..0dbf366 100644
--- a/stitch_kintex_ai_system_architect/exhibition_schedule_kintex_ai_system/code.html
+++ b/stitch_kintex_ai_system_architect/exhibition_schedule_kintex_ai_system/code.html
@@ -5,9 +5,9 @@
Exhibition Schedule - KINTEX CMS
-
-
-
+
+
+
-