From 4cee6c1f6617280e0b09ba568bc15d1f8c239fa8 Mon Sep 17 00:00:00 2001 From: zio Date: Sat, 11 Jul 2026 21:56:28 +0900 Subject: [PATCH] =?UTF-8?q?feat(frontend):=20=EC=8B=A0=EA=B7=9C=205?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20SCR-13~17=20=E2=80=94=20=EA=B2=BD=EC=98=81?= =?UTF-8?q?=EB=B6=84=EC=84=9D=C2=B7=ED=98=84=EC=9E=A5=EC=9A=B4=EC=98=81?= =?UTF-8?q?=C2=B7=EC=A0=84=EC=8B=9C=EC=9D=BC=EC=A0=95=C2=B7=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=EC=9E=90=C2=B7=EC=8A=A4=ED=83=80=EC=9D=BC=EA=B0=80?= =?UTF-8?q?=EC=9D=B4=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - design.md v1.3: SCR-13~17 매핑·상세 스펙 순증 (기존 SCR-01~12 무수정) - React 이식 5화면 + Recharts 도입 + chartColors(§1 토큰)·shared.css 공통 프리미티브 - App.tsx 라우트 5종 + AppShell NavLink 배선 (신규 4항목, /_styleguide 네비 비노출) - QA: tsc 위양성 교정(tsconfig.app 기준)·미사용 import 제거 → tsc/vite build EXIT 0 - reviewer: 배포 가능(Critical/Major 0) — Minor 티켓 BACKLOG 등재, R15-01 홀 필터 배선 즉시 수정 - docs: UNDEVELOPED_BACKLOG.md 신설(세션 미개발 통합) + WORK_STATUS 갱신 - stitch: 재취득 4화면 + component_guide 2종 + _icons 7종 Co-Authored-By: Claude Fable 5 --- docs/BACKLOG.md | 11 + docs/UNDEVELOPED_BACKLOG.md | 79 +++ docs/WORK_STATUS.md | 4 +- docs/design.md | 135 +++- src/frontend/package-lock.json | 391 +++++++++++ src/frontend/package.json | 1 + src/frontend/src/App.tsx | 15 + .../src/components/layout/AppShell.tsx | 35 +- .../src/screens/admin/AdminDashboardPage.tsx | 140 ++++ src/frontend/src/screens/admin/admin.css | 158 +++++ src/frontend/src/screens/admin/sampleAdmin.ts | 58 ++ .../analytics/AnalyticsDashboardPage.tsx | 246 +++++++ .../src/screens/analytics/analytics.css | 75 +++ .../src/screens/analytics/sampleAnalytics.ts | 123 ++++ src/frontend/src/screens/chartColors.ts | 26 + .../src/screens/ops/HallOperationsPage.tsx | 193 ++++++ src/frontend/src/screens/ops/ops.css | 317 +++++++++ src/frontend/src/screens/ops/sampleOps.ts | 65 ++ .../schedule/ExhibitionSchedulePage.tsx | 213 ++++++ .../src/screens/schedule/sampleSchedule.ts | 99 +++ .../src/screens/schedule/schedule.css | 221 +++++++ src/frontend/src/screens/shared.css | 205 ++++++ .../screens/styleguide/ComponentGuidePage.tsx | 198 ++++++ .../src/screens/styleguide/styleguide.css | 285 ++++++++ .../_icons/icon_ai_bot/code.html | 11 + .../_icons/icon_ai_bot/screen.png | Bin 0 -> 2089 bytes .../_icons/icon_analytics/code.html | 5 + .../_icons/icon_analytics/screen.png | Bin 0 -> 425 bytes .../_icons/icon_calendar/code.html | 6 + .../_icons/icon_calendar/screen.png | Bin 0 -> 580 bytes .../_icons/icon_dashboard/code.html | 5 + .../_icons/icon_dashboard/screen.png | Bin 0 -> 547 bytes .../_icons/icon_menu/code.html | 5 + .../_icons/icon_menu/screen.png | Bin 0 -> 358 bytes .../_icons/icon_operations/code.html | 6 + .../_icons/icon_operations/screen.png | Bin 0 -> 1190 bytes .../_icons/icon_search/code.html | 4 + .../_icons/icon_search/screen.png | Bin 0 -> 953 bytes .../code.html | 74 ++- .../code.html | 48 +- .../code.html | 566 ++++++++++++++++ .../code.html | 616 ++++++++++++++++++ .../code.html | 46 +- .../code.html | 36 +- 44 files changed, 4614 insertions(+), 107 deletions(-) create mode 100644 docs/UNDEVELOPED_BACKLOG.md create mode 100644 src/frontend/src/screens/admin/AdminDashboardPage.tsx create mode 100644 src/frontend/src/screens/admin/admin.css create mode 100644 src/frontend/src/screens/admin/sampleAdmin.ts create mode 100644 src/frontend/src/screens/analytics/AnalyticsDashboardPage.tsx create mode 100644 src/frontend/src/screens/analytics/analytics.css create mode 100644 src/frontend/src/screens/analytics/sampleAnalytics.ts create mode 100644 src/frontend/src/screens/chartColors.ts create mode 100644 src/frontend/src/screens/ops/HallOperationsPage.tsx create mode 100644 src/frontend/src/screens/ops/ops.css create mode 100644 src/frontend/src/screens/ops/sampleOps.ts create mode 100644 src/frontend/src/screens/schedule/ExhibitionSchedulePage.tsx create mode 100644 src/frontend/src/screens/schedule/sampleSchedule.ts create mode 100644 src/frontend/src/screens/schedule/schedule.css create mode 100644 src/frontend/src/screens/shared.css create mode 100644 src/frontend/src/screens/styleguide/ComponentGuidePage.tsx create mode 100644 src/frontend/src/screens/styleguide/styleguide.css create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_ai_bot/code.html create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_ai_bot/screen.png create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_analytics/code.html create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_analytics/screen.png create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_calendar/code.html create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_calendar/screen.png create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_dashboard/code.html create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_dashboard/screen.png create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_menu/code.html create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_menu/screen.png create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_operations/code.html create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_operations/screen.png create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_search/code.html create mode 100644 stitch_kintex_ai_system_architect/_icons/icon_search/screen.png create mode 100644 stitch_kintex_ai_system_architect/component_guide_kintex_ai_system/code.html create mode 100644 stitch_kintex_ai_system_architect/component_guide_updated_kintex_ai_system/code.html 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) => ( +
+
+ )) + )} + {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 ( +
+
+
+

System Reference

+

컴포넌트 가이드

+

+ KINTEX AI 디자인 시스템 — 고신뢰·정밀 정보 처리 B2B 전시 환경. 색·치수 권위는 design.md §1. +

+
+ design.md v1.3 · 내부 전용 +
+ +
+ {/* 1. 타이포 & 컬러 */} +
+

타이포그래피 & 컬러

+
+

전시공간 최적화 엔진

+

도면 분석 보고서

+

부스 배치 시뮬레이션

+

+ 본문 텍스트 — 참가업체 설계 스펙과 규정 검증 결과를 정밀하게 표시합니다. Pretendard 14px. +

+
+
+ {SWATCHES.map((s) => ( +
+ + {s.name} + {s.hex} +
+ ))} +
+
+ + {/* 2. AI 전용 요소 */} +
+

AI 전용 요소

+
+ + 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 0000000000000000000000000000000000000000..0fdd0a0f031d1f5315ef33cdac89d87691db9b80 GIT binary patch literal 2089 zcmV+^2-f$BP)aB^>EX>4U6ba`-PAVE-2F#rGb^3Iibwy!(oM!kEOU z&yliQ7D`+8|A$7@c7?VROmr|aiMy`%_1G`V^LT9gZFNfp0Zy`HDgY8181MvNtL27X z+1t&U5c`{2)tn;a^sit-upi3mqn*}JQ*JskY?&-fqu`r2>X0W79pe0h4>Mo-OoSqJ z2kLwpdk;BpAu60LqAEwumPv`(<_nDf(M_5!efA4vdZ}~s-u~TZa4+p~Rto#X#|;1g z2Np?0K~#90?VN3lTvZvzf6tu(N{v!Pr5b}tTNSA!^(AT{LL-58X4_IxqZlfL5R-Oi z*7O6V#+XiHR6r6-XSXH#K?qcdA)(lIW?O5r8aJS+))%VASfa*Ms}|6t*p;38_d{pv z?A^Kha_^nFcedx3Y_jv*J^%CU`Omp?&bf0AI2;Z~YFOF{L}7DLi*xWGa7#0ExB**t z*X(a;<`so}+6hF#6JN*pR7+^1CoTeRPb;UWcxfjPk-{uvnWt9`m^bvQ0rgqNGEYw$ z;2T>2Q1hoX)?@VKCaXaZ$X}T zDzU~_$nP;QxY@s$y~(J}j;+5RWe$%bGXCjzOH%De}9*{E5fRu3tq>M8lWjZnw-m+4c{`WFgc*Y7DS2imO zjx=_3qVA}K_#yC@ICW%zx0+amu{3zWj0Jh|I7DA$ zjNAiCYqZTgz8Z`Reqs#KbUuGPq!B?t>>|j{A&>qlV)LOwl;5yg%bEny6*OB8u{~8s;{w}l!c<}j-WY&iM zqSl(&X2x;=iQ_WvAFA1bUeKQj&*KX~t?jk2LK5%nSVk?B3fkbo{^kPLB4Cjj*L$$P zRM3X3>(2^tb=aj)1I)Oh^>wvoHu00>19gM@qFl?0{se*@t!)&j==EXcQXd5g-WBCq zR`lbNx&aqDsT*MM+bGwvq92#k4G=sK) zgm^KmT=;5e24;!#h3VQd+yLYL&ZKie^5w7#p#}`q>_Bq{`7Gk!oylwdB6vw+)c5Hd ztXt@bj?>PB!)B1BqAI~nZAnvJtv-1?V1^L8t99Emr}71D67-uP-{-!eVQc$DDk%gz z25VNCYq?A;MFgp=QvS5ZH*Mk@*v9TsL2DK?`1C`E?aXv#?_RIhE_{_IFxF2z6)}&& z3R+gd{0^r+XEHksRp1mLGuDsgIkve^p$}0?MP0jaoL`!;eo|Rw_jt~1_J9!^A1G>z zFP=1;)Oc_A#IH+5jUx8@KKsaXk>|6{jJ2HGDm3X$B_YJtEWZ08qXq!%s@Zo3iW+O0 zaDE?}K@PY9 zk(-jhibz_s;2ZnxpTMTgMeWFmb%G5T%TV)RCF3OLjuH6Ys|}uc{i2_ZAgraz3AlBOhxXFjTWY3GRub(aV@|_s&BWY4~|wBZ)-% zi+YC#-=>QPo~F#t5TDG%flU)skaxPkHjM4S#YyRA3Na>8dBZRdCbhPd_$uLDtF+)X zm$20HSR!KyaCy>obeWe-ya1fY(rLdAhr{7;I2;a#!{Kl^91e%W;cz${j#=_Q{6#`1 T2qs0-00000NkvXXu0mjfGcE1? literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..6e0f742d1c529ae80460eeffe9fa75197ab60cd8 GIT binary patch literal 425 zcmV;a0apHrP)aB^>EX>4U6ba`-PAVE-2F#rGdq3d0}_eD^E*3715p zevXWG6vj6C{|}3(w8FNCIX#kG&fVANdhEC5eZ02)vAU%O1I}lkxd2FLApkL`qU9DH zh3sWbi2ctEHKz!FsVkTwScQsGwA&hL%59Dxvch(3M!`32)FrPPW4Qd_!_1ey6QlU* zfjggu?=dc_im2D1LC8>*jL4FVVMF{sU8L#q=`YmY)VbL=$+J5`#6hGwTqzt9i@xDmiD z5}@2W9Tk12qkSM+FDcdsvfp+3z$+2JjR0;0a3g@*uL3L=->&+w=s2BS4*&&hyjw7M T@olPG00000NkvXXu0mjfj)1qG literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..0483f7bc7d9db0976bd9fe10763085044f67a1f7 GIT binary patch literal 580 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmSQK*5Dp-y;YjHK^7mJTM3e+2 zmMat#<)>xlq$-qD7NjaT1_T%~Fi1?T^^fLaR^<8fU8K6@fhb; z^1IN#uWPdFdjmtSf4>~Km%hK~sr}}iwbs7E#hrhi%sBm&UG98^>@11U+q^a(Y~Ig% zeI#_ngy&BJb!SQLv=TO(9QOCC1GH|NWhGZYD_lpY6u^cHNVR)UOPCS~`Lbi6?N>FiEysmqiIx-VL{_Et^vv zpb~ISdjprj*A-C=ZN?90u|cOO2BD;&1*3n2xx8 zmiNe2wS#buF&#lcq6x}%@wacRVzT@mrTptrQTE2-_;{_D=z_lK-n@4MgU zz?wBHui41(S=0#`%)QQ(A<8+ym_cnv{|vd<`UC8Z?mlga5?42{3mbZzUocPZ1TYye Nc)I$ztaD0e0szto`9S~x literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..f0f6afb1db26a912039d925b202e556be4b70f8d GIT binary patch literal 547 zcmV+;0^I$HP)aB^>EX>4U6ba`-PAVE-2F#rGb^3Iibwy!(oM!kE#h z&ylh%3#Bdl|3f1x+l96XCUHnI8FyPB>%Lu<*Z#b2_th=U1aP5*A{9VJHv(SZTejG3 zWO}P?2xw{phIJN$2vb-ljSH1;w=g;HIu{Vss8vgX?GaC_w21`s-_4N!kaAfXS; luz6-Z0uw%bW_6r@;R;}qL)Kff?QsAA002ovPDHLkV1fbz=&S$$ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..a97c4447d98215819a71e62b47b93bc563f67229 GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmSQK*5Dp-y;YjHK@^@8*M3e+2 zmMat#<)>xlq$-qD7NjaT1_T%~Fi1?T^$+AbWWe$Fy=GZU_<}9Ae#y%sldin^Cm(cr zlWw5A<^}NwjyulwSH|jH&aRD{{##}lA5&Av$}0>aJO%=s8{I!M%UMRH`JVWSF12fQa$n9SpER?@4`-YGn&jS_Yw`cV<(c{Wgco}5Z=9ol`z~K< zbC!|*tPqRW4XN^n>x(BY^!{DjxudA?T}}Cu+Uyqd529gWLbfT_L7ww;aSX|5e0$B1 zt091g`N9K5+u!?p_4uq_&UjRP!M4?DG6O^GHx=!Zfo88yeOqPtr?#{G?P<5mJ@$$W z|8oB*XY;J*Hto@4IiUVnJ~Fu?c12=|BEyPeCT_DB76xVhy+A7%JYD@<);T3K0RUpe Biva)t literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..8df28ded1624cf9db2ad79b3fe9a47c8f82802e5 GIT binary patch literal 1190 zcmV;X1X=ruP)aB^>EX>4U6ba`-PAVE-2F#rGdq3d0}_eD^E*3715p zevXWG6vj6C{|}3p(iXN|FwrC4CE-3l=WV@B@9nj$k2y>o41`!?+0OXTQyn^Sw-vT9jfQXD=tG`8c5(T^rz_ulCPs^W z2X?;fdpk5KX%vxa!Ky-%EgLJ^A^0C|GJN^iFR|$r=dOE`98)8F0PVq65Y;cwHvj+w zlu1NERA_*c&1s+Ebo6Bl} z+07w*C~&2S!qqO?98H2nIVQggYy!puRX{hOwOKdwO|YDMIk*-UTl~5#lkEa}7QopH z*qeoSbz?=RuqkAM)4;$$UILf_90qRTI?h+z0NBJ(&(4{nfH5chz8SonzV6nBH$+i_BJcu%2hlh8i#j8BA znb`<+VIDAlSKQ$%7^@E9NCNwS^S~Rk^SDiGc*vL|!u=lTY_V#IoeC4*ip+&G#A18I ze-~&W;}gJE+*1qdHotHiV?xGO01qU0r^SYe|C?#ez+_2$ZvM8O!e+_XmcX?v!qu+Y zm>~4^4GMiNv5CF{woB4(^UoCjOEP~5ZHyp3W$T5b4A<|2Inyk*U;JBBgUSO0RYG{( zKBtQRsF9>F3|J#M$AHnemRM=mCnRSb=||_k#vQ~I(GsQ=fZO;V(+%lWoK1%_eCHIxY6B7Su{>l)4+8THixW11&#{)bOzv8DyM85bV-+#y)b@o{w;!ndI zTra+F*SY*DoFx73Bt1DPBqjHF5p@)d%_1t>BGzIz6jMl{=!5&|sCRZG&=Kfj*V=); z5b=!PlvqXdjci3pl!l-M(f%*GOy*gt_{D_ReZMNbipX*ztalc z^qOR@^4ux^H{t?HjkthPBQBuShzlq+;sRpCh*4Vn16_+W_Rj!uRR91007*qoM6N<$ Eg8JDqOaK4? literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..482c155fde637babe7a20a9872369ca6005f53e5 GIT binary patch literal 953 zcmV;q14jIbP)aB^>EX>4U6ba`-PAVE-2F#rGc94#OY_{r40-!V?tr zIA&>=Cd;<;{vX4LX-&300_Y3yz}?s9dhEC5eZ02)vAU&!02fLqQ~_jkFyINkWsMz{ z+3QQ2knB%AOUVi0Qdcn{YK5@)q~04^D1A;CvP^0^qvD%3+LBj|F`R$!aptS-M5v+N zK*r~Bw?T+mcgYetseARtu!t}hHT*Xd>AG~@7fE}war51t&#mD;=oMB3EKDJS00080 zNkl1us%xYX&Tv3c*BO(|?`~fzCVo>81!GEA)W3aKY(9R-8f<-zD zHDVz)qG%ylsMu%}5rfeP1~kSC7%zzzSc~rvW%8AbO~c04uT%Ujtr+ zn7;vffO#Go?Z6S>ZHUgO^T>oY;9iL7RiM&@UKJTSTJMhYGUr%`S#L_s63`!_do-nP zfF-~;Wpdt7e^6ZUoX#9v~x zPI0soeBTTh>a!g9sSE}U^{*)HDPXCgJ|LSHz47QH-NLSf?C7-a$y7-rr~r>c%&s9D z_oP&Tn<08*$dJl}4uWH~4!lMtp)XzTny}M}I&wge8LNmsR=Euv2R0+eDi!2Tce>Cg z+;5_S&sq^R;I3y7pB8mPGA*JNH~_p)5qtvJkE{fG@+bmi4c|}l!`)K^j}vn%0_3f^ z1KAc1A(MRy_>N52hrmVmo4A9kT#K;czb#@In3HFyr061^^N$q(a1c4 +```html - - - + + KINTEX AI CMS - Dashboard - - - + + - + + + + + + + + + + +
+
+Exhibition Studio + +
+
+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 +
+
+
+

KINTEX Blue

+

#004E8B

+
+
+

AI Accent

+

#6D4AFF

+
+
+

Success

+

#00734E

+
+
+

Error/Alert

+

#BA1A1A

+
+
+

Neutral Low

+

#F1F3FF

+
+
+
+
+
+ +
+
+

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% +
+
+ +
+

혼잡도 히트맵 범례

+
+
+매우 혼잡 (Bottle Neck) +
+
+
+다소 혼잡 +
+
+
+원활 (Optimized) +
+
+ +
+

방문객 추이 (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 + + + + + + + + + + +
+
+Exhibition Studio + +
+
+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 +
+
+
+

KINTEX Blue

+

#004E8B

+
+
+

AI Accent

+

#6D4AFF

+
+
+

Success

+

#00734E

+
+
+

Error/Alert

+

#BA1A1A

+
+
+

Neutral Low

+

#F1F3FF

+
+
+
+
+
+ +
+
+

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% +
+
+ +
+

혼잡도 히트맵 범례

+
+
+매우 혼잡 (Bottle Neck) +
+
+
+다소 혼잡 +
+
+
+원활 (Optimized) +
+
+ +
+
+

방문객 추이 (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 - - - + + + -