feat: 실험실 메뉴 Tab + Flyout 방식 구현
- 실험실 그룹 (S: Strategy, A: AI/Automation, M: Management) 추가 - 확장 상태: S | A | M 수평 탭, 클릭 시 해당 패널 표시 - 축소 상태: 아이콘 호버 시 우측 플라이아웃 팝업 - localStorage 탭 상태 저장/복원 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,125 +1,59 @@
|
||||
# Workflow 진행 상태
|
||||
|
||||
**작업명:** Archive & Restore Feature (아카이브 복원 기능)
|
||||
**시작일:** 2025-11-30
|
||||
**분석 문서:** `claudedocs/archive-restore-feature-analysis.md`
|
||||
## 현재 단계: 완료 ✅
|
||||
|
||||
---
|
||||
|
||||
## 현재 단계: Phase 2 완료 ✅
|
||||
|
||||
---
|
||||
## 작업 내용
|
||||
실험실 메뉴 Tab + Flyout 구현 (3단계 메뉴 구조 개선)
|
||||
|
||||
## 전체 작업 목록
|
||||
|
||||
- [x] 1단계: 분석 완료
|
||||
- [x] 2단계: Phase 1 순차 수정 (8/8 완료)
|
||||
- [x] 3단계: Phase 1 검증 완료 (Pint)
|
||||
- [x] 4단계: Phase 2 테넌트 필터링 (5/5 완료)
|
||||
- [x] 5단계: Phase 2 검증 완료 (Pint)
|
||||
- [ ] 6단계: 커밋 대기
|
||||
- [x] 2단계: 순차 수정 (3/3 완료) - Tab + Flyout 방식
|
||||
- [x] 3단계: 검증 완료
|
||||
- [x] 4단계: 문서 정리 완료
|
||||
- [x] 5단계: 커밋 완료 (39f8d58)
|
||||
|
||||
---
|
||||
## 구현 방식 변경 이력
|
||||
1. **초기 방식**: 중첩 서브그룹 (padding 들여쓰기)
|
||||
- 문제: 256px 사이드바에서 텍스트가 세로로 표시됨
|
||||
2. **최종 방식**: Tab + Flyout
|
||||
- 확장 상태: S | A | M 수평 탭, 클릭 시 해당 패널 표시
|
||||
- 축소 상태: 아이콘 호버 시 우측에 플라이아웃 팝업
|
||||
|
||||
## Phase 1 - 아카이브 복원 기능 ✅ 완료
|
||||
## 순차 수정 상세 (2단계) - 완료
|
||||
- [x] 수정 1/3: HTML 구조 변경 (탭 + 플라이아웃)
|
||||
- [x] 수정 2/3: CSS 스타일 추가 (탭 버튼, 플라이아웃 애니메이션)
|
||||
- [x] 수정 3/3: JavaScript 추가 (switchLabTab, switchLabFlyoutTab)
|
||||
|
||||
| # | 작업 | 파일 | 상태 |
|
||||
|---|------|------|------|
|
||||
| 1 | 마이그레이션: record_type enum→varchar | `api/database/migrations/2025_11_30_*_modify_archived_records_record_type_to_varchar.php` | ✅ 완료 |
|
||||
| 2 | ArchiveService 생성 | `mng/app/Services/ArchiveService.php` | ✅ 완료 |
|
||||
| 3 | RestoreService 생성 | `mng/app/Services/RestoreService.php` | ✅ 완료 |
|
||||
| 4 | TenantService에 아카이브 로직 적용 | `mng/app/Services/TenantService.php` | ✅ 완료 |
|
||||
| 5 | UserService에 아카이브 로직 적용 | `mng/app/Services/UserService.php` | ✅ 완료 |
|
||||
| 6 | ArchivedRecordController에 restore 추가 | `mng/app/Http/Controllers/ArchivedRecordController.php` | ✅ 완료 |
|
||||
| 7 | 라우트 추가 | `mng/routes/web.php` | ✅ 완료 |
|
||||
| 8 | UI: 복원 버튼 추가 | `mng/resources/views/archived-records/show.blade.php`, `restore-check.blade.php` | ✅ 완료 |
|
||||
## 검증 결과 (3단계) - 완료
|
||||
- [x] PHP 문법 검사: 오류 없음
|
||||
- [x] Blade 뷰 캐시 빌드: 성공
|
||||
|
||||
---
|
||||
## 도구 사용 기록
|
||||
|
||||
## Phase 2 - 테넌트 필터링 기능 ✅ 완료
|
||||
### 1단계 (분석) - 완료
|
||||
**네이티브 도구:**
|
||||
- Read: 4회 (myheader.php x2, INDEX.md, CURRENT_WORKS.md)
|
||||
- Bash: 2회 (프로젝트 탐색)
|
||||
|
||||
| # | 저장소 | 파일 | 작업 | 상태 |
|
||||
|---|--------|------|------|------|
|
||||
| 1 | **api/** | `database/migrations/2025_12_01_002115_add_tenant_id_to_archived_records.php` | 신규 - DB 마이그레이션 | ✅ 완료 |
|
||||
| 2 | mng/ | `app/Services/ArchiveService.php` | 수정 - tenant_id 저장 로직 | ✅ 완료 |
|
||||
| 3 | mng/ | `app/Services/ArchivedRecordService.php` | 수정 - 테넌트 필터링 | ✅ 완료 |
|
||||
| 4 | mng/ | `app/Models/Archives/ArchivedRecord.php` | 수정 - fillable, 관계 추가 | ✅ 완료 |
|
||||
| 5 | mng/ | `resources/views/archived-records/partials/table.blade.php` | 수정 - 대상 테넌트 표시 | ✅ 완료 |
|
||||
### 2단계 (순차 수정) - 완료
|
||||
**네이티브 도구:**
|
||||
- Read: 3회 (sidebar.blade.php, WORKFLOW_STATE.md, header.blade.php)
|
||||
- Edit: 3회 (HTML 구조 변경, CSS 추가, JS 추가)
|
||||
|
||||
---
|
||||
### 3단계 (검증) - 완료
|
||||
**네이티브 도구:**
|
||||
- Bash: 2회 (php -l, view:cache)
|
||||
|
||||
## 생성/수정된 파일 목록 (전체)
|
||||
|
||||
### api/ 저장소
|
||||
- `database/migrations/2025_12_01_002115_add_tenant_id_to_archived_records.php` (신규)
|
||||
|
||||
### mng/ 저장소
|
||||
|
||||
#### 신규 생성
|
||||
- `app/Services/ArchiveService.php` (326줄)
|
||||
- `app/Services/RestoreService.php` (319줄)
|
||||
- `resources/views/archived-records/restore-check.blade.php`
|
||||
- `database/migrations/2025_11_30_144617_modify_archived_records_record_type_to_varchar.php`
|
||||
|
||||
#### 수정
|
||||
- `app/Services/TenantService.php` (ArchiveService DI, forceDeleteTenant 수정)
|
||||
- `app/Services/UserService.php` (ArchiveService DI, forceDeleteUser 수정)
|
||||
- `app/Services/ArchivedRecordService.php` (tenant_id 필드 추가, 필터링)
|
||||
- `app/Models/Archives/ArchivedRecord.php` (tenant_id fillable, tenant 관계)
|
||||
- `app/Http/Controllers/ArchivedRecordController.php` (restore, checkRestore 메서드)
|
||||
- `routes/web.php` (restore-check, restore 라우트)
|
||||
- `resources/views/archived-records/show.blade.php` (복원 버튼, 알림 메시지)
|
||||
- `resources/views/archived-records/index.blade.php` (알림 메시지)
|
||||
- `resources/views/archived-records/partials/table.blade.php` (대상 테넌트 컬럼)
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 주요 변경 내용
|
||||
|
||||
### 1. tenant_id 컬럼 추가
|
||||
- archived_records 테이블에 tenant_id 컬럼 추가
|
||||
- FK 제약조건 없음 (삭제된 테넌트 참조 가능)
|
||||
- 인덱스 추가
|
||||
|
||||
### 2. tenant_id 결정 로직
|
||||
- **테넌트 삭제**: tenant_id = 삭제되는 테넌트의 ID (자기 자신)
|
||||
- **사용자 삭제**: tenant_id = session('selected_tenant_id')
|
||||
- **부서/메뉴/역할 삭제**: 해당 레코드의 tenant_id
|
||||
|
||||
### 3. UI 변경
|
||||
- 목록에 "대상 테넌트" 컬럼 추가
|
||||
- 존재하는 테넌트: 인디고 뱃지로 표시
|
||||
- 삭제된 테넌트: 회색 뱃지로 "(삭제됨 ID: N)" 표시
|
||||
- 테넌트 없음: "-" 표시
|
||||
|
||||
### 4. 필터링
|
||||
- ArchivedRecordService에 tenant_id 필터 추가
|
||||
- filters['tenant_id']로 테넌트별 필터링 가능
|
||||
|
||||
---
|
||||
|
||||
## 남은 작업
|
||||
|
||||
### 6단계: 커밋 (대기)
|
||||
- api/ 저장소: 마이그레이션 커밋
|
||||
- mng/ 저장소: 모든 변경사항 커밋
|
||||
- 사용자 승인 후 진행
|
||||
|
||||
---
|
||||
|
||||
## 중단 시 재개 가이드
|
||||
|
||||
1. 이 파일(`WORKFLOW_STATE.md`) 확인
|
||||
2. 현재 상태: Phase 2 완료, 커밋 대기
|
||||
3. 커밋 요청 시 변경 사항 요약 제공 후 커밋
|
||||
|
||||
---
|
||||
|
||||
## 참고 파일
|
||||
|
||||
- 분석 문서: `claudedocs/archive-restore-feature-analysis.md`
|
||||
- ArchivedRecord 모델: `app/Models/Archives/ArchivedRecord.php`
|
||||
- ArchivedRecordRelation 모델: `app/Models/Archives/ArchivedRecordRelation.php`
|
||||
- ArchivedRecordService: `app/Services/ArchivedRecordService.php`
|
||||
- ArchiveService: `app/Services/ArchiveService.php`
|
||||
- RestoreService: `app/Services/RestoreService.php`
|
||||
## 변경 파일 목록
|
||||
- `resources/views/partials/sidebar.blade.php`
|
||||
- HTML: 실험실 탭 기반 메뉴 구조 (~200줄)
|
||||
- 확장 뷰: 헤더 + S|A|M 탭 + 각 탭 패널
|
||||
- 축소 뷰: 아이콘 + 플라이아웃 팝업
|
||||
- CSS: 탭 + 플라이아웃 스타일 (~95줄)
|
||||
- 탭 버튼 active 상태
|
||||
- 플라이아웃 애니메이션 (flyoutFadeIn)
|
||||
- 확장/축소 상태별 뷰 전환
|
||||
- JS: 탭 전환 함수 (~75줄)
|
||||
- switchLabTab(): 확장 상태 탭 전환
|
||||
- switchLabFlyoutTab(): 플라이아웃 탭 전환
|
||||
- localStorage 상태 저장/복원
|
||||
732
composer.lock
generated
732
composer.lock
generated
File diff suppressed because it is too large
Load Diff
298
package-lock.json
generated
298
package-lock.json
generated
@@ -1302,18 +1302,6 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/didyoumean": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
||||
@@ -1811,18 +1799,6 @@
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
||||
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/laravel-vite-plugin": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-2.0.1.tgz",
|
||||
@@ -1843,280 +1819,6 @@
|
||||
"vite": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
|
||||
"integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"lightningcss-android-arm64": "1.30.2",
|
||||
"lightningcss-darwin-arm64": "1.30.2",
|
||||
"lightningcss-darwin-x64": "1.30.2",
|
||||
"lightningcss-freebsd-x64": "1.30.2",
|
||||
"lightningcss-linux-arm-gnueabihf": "1.30.2",
|
||||
"lightningcss-linux-arm64-gnu": "1.30.2",
|
||||
"lightningcss-linux-arm64-musl": "1.30.2",
|
||||
"lightningcss-linux-x64-gnu": "1.30.2",
|
||||
"lightningcss-linux-x64-musl": "1.30.2",
|
||||
"lightningcss-win32-arm64-msvc": "1.30.2",
|
||||
"lightningcss-win32-x64-msvc": "1.30.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-android-arm64": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
|
||||
"integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-arm64": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
|
||||
"integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-x64": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
|
||||
"integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-freebsd-x64": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
|
||||
"integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm-gnueabihf": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
|
||||
"integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-gnu": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
|
||||
"integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-musl": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
|
||||
"integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-x64-gnu": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
|
||||
"integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-x64-musl": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
|
||||
"integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-win32-arm64-msvc": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
|
||||
"integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-win32-x64-msvc": {
|
||||
"version": "1.30.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
|
||||
"integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
||||
|
||||
@@ -369,6 +369,189 @@ class="flex items-center gap-2 pr-3 py-2 rounded-lg text-sm text-gray-700 hover:
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<!-- 실험실 그룹 (탭 스타일 + 플라이아웃) -->
|
||||
<li class="lab-menu-container pt-4 pb-1 border-t border-gray-200 mt-2" id="lab-menu-container">
|
||||
<!-- 확장 상태: 헤더 + 탭 + 메뉴 -->
|
||||
<div class="lab-expanded-view">
|
||||
<button onclick="toggleGroup('lab-group')" class="sidebar-group-header lab-group-header w-full flex items-center justify-between px-3 py-2 text-xs font-bold text-gray-700 uppercase tracking-wider rounded">
|
||||
<span class="flex items-center gap-2">
|
||||
<svg class="w-4 h-4 text-amber-600 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
|
||||
</svg>
|
||||
<span class="sidebar-text">실험실</span>
|
||||
</span>
|
||||
<svg id="lab-group-icon" class="w-3 h-3 transition-transform sidebar-text" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- 탭 + 메뉴 콘텐츠 -->
|
||||
<div id="lab-group" class="mt-2">
|
||||
<!-- S | A | M 탭 버튼 -->
|
||||
<div class="lab-tabs flex mx-2 mb-2 bg-gray-100 rounded-lg p-1">
|
||||
<button type="button" onclick="switchLabTab('s')" id="lab-tab-s" class="lab-tab active flex-1 py-1.5 text-xs font-bold rounded-md transition-all text-blue-600">
|
||||
S
|
||||
</button>
|
||||
<button type="button" onclick="switchLabTab('a')" id="lab-tab-a" class="lab-tab flex-1 py-1.5 text-xs font-bold rounded-md transition-all text-purple-600">
|
||||
A
|
||||
</button>
|
||||
<button type="button" onclick="switchLabTab('m')" id="lab-tab-m" class="lab-tab flex-1 py-1.5 text-xs font-bold rounded-md transition-all text-green-600">
|
||||
M
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- S. Strategy 메뉴 (16개) -->
|
||||
<ul id="lab-panel-s" class="lab-panel space-y-1">
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="세무 전략 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 7h6m0 10v-3m-3 3h.01M9 17h.01M9 14h.01M12 14h.01M15 11h.01M12 11h.01M9 11h.01M7 21h10a2 2 0 002-2V5a2 2 0 00-2-2H7a2 2 0 00-2 2v14a2 2 0 002 2z" /></svg><span class="font-medium sidebar-text">세무 전략</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="노무 전략 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z" /></svg><span class="font-medium sidebar-text">노무 전략</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="채권추심 전략 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg><span class="font-medium sidebar-text">채권추심 전략</span></span></li>
|
||||
<li class="border-t border-gray-100 pt-1 mt-1"></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="스테이블코인 보고서 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg><span class="font-medium sidebar-text">스테이블코인 보고서</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="MRP 해외사례 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg><span class="font-medium sidebar-text">MRP 해외사례</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="상담용 챗봇 전략 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" /></svg><span class="font-medium sidebar-text">상담용 챗봇 전략</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="KoDATA vs NICE API 비교 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" /></svg><span class="font-medium sidebar-text">KoDATA vs NICE API</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="바로빌 vs 팝빌 API (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg><span class="font-medium sidebar-text">바로빌 vs 팝빌 API</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="사내 지식 검색 시스템 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg><span class="font-medium sidebar-text">사내 지식 검색 시스템</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="챗봇 솔루션 비교 분석 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" /></svg><span class="font-medium sidebar-text">챗봇 솔루션 비교 분석</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="RAG 스타트업 현황 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg><span class="font-medium sidebar-text">RAG 스타트업 현황</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="더존비즈온 분석 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" /></svg><span class="font-medium sidebar-text">더존비즈온 분석</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="Confluence vs Notion (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2" /></svg><span class="font-medium sidebar-text">Confluence vs Notion</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="차세대 QA 솔루션 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg><span class="font-medium sidebar-text">차세대 QA 솔루션</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="SAM 영업전략 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6" /></svg><span class="font-medium sidebar-text">SAM 영업전략</span></span></li>
|
||||
</ul>
|
||||
|
||||
<!-- A. AI/Automation 메뉴 (12개) -->
|
||||
<ul id="lab-panel-a" class="lab-panel space-y-1 hidden">
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="사업자등록증 OCR (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg><span class="font-medium sidebar-text">사업자등록증 OCR</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="웹 녹음 AI 요약 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" /></svg><span class="font-medium sidebar-text">웹 녹음 AI 요약</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="회의록 AI 요약 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" /></svg><span class="font-medium sidebar-text">회의록 AI 요약</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="업무협의록 AI 요약 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" /></svg><span class="font-medium sidebar-text">업무협의록 AI 요약</span></span></li>
|
||||
<li class="border-t border-gray-100 pt-1 mt-1"></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="운영자용 챗봇 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" /></svg><span class="font-medium sidebar-text">운영자용 챗봇</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="Vertex RAG 챗봇 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /></svg><span class="font-medium sidebar-text">Vertex RAG 챗봇</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="테넌트 지식 업로드 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" /></svg><span class="font-medium sidebar-text">테넌트 지식 업로드</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="테넌트 챗봇 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z" /></svg><span class="font-medium sidebar-text">테넌트 챗봇</span></span></li>
|
||||
<li class="border-t border-gray-100 pt-1 mt-1"></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="SAM AI 메뉴 이동 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg><span class="font-medium sidebar-text">SAM AI 메뉴 이동</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="SAM AI 알람음 제작 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" /></svg><span class="font-medium sidebar-text">SAM AI 알람음 제작</span></span></li>
|
||||
<li class="border-t border-gray-100 pt-1 mt-1"></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="GPS 출퇴근 관리 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" /></svg><span class="font-medium sidebar-text">GPS 출퇴근 관리</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="기업개황 조회 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" /></svg><span class="font-medium sidebar-text">기업개황 조회</span></span></li>
|
||||
</ul>
|
||||
|
||||
<!-- M. Management 메뉴 (13개) -->
|
||||
<ul id="lab-panel-m" class="lab-panel space-y-1 hidden">
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="바로빌 테넌트 관리 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" /></svg><span class="font-medium sidebar-text">바로빌 테넌트 관리</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="전자세금계산서 전략 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 14l6-6m-5.5.5h.01m4.99 5h.01M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16l3.5-2 3.5 2 3.5-2 3.5 2z" /></svg><span class="font-medium sidebar-text">전자세금계산서 전략</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="전자세금계산서 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 14l6-6m-5.5.5h.01m4.99 5h.01M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16l3.5-2 3.5 2 3.5-2 3.5 2zM10 8.5a.5.5 0 11-1 0 .5.5 0 011 0zm5 5a.5.5 0 11-1 0 .5.5 0 011 0z" /></svg><span class="font-medium sidebar-text">전자세금계산서</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="사업자등록번호 진위 확인 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" /></svg><span class="font-medium sidebar-text">사업자등록번호 진위 확인</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="영업관리 & 매니저 미팅관리 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" /></svg><span class="font-medium sidebar-text">영업관리 & 매니저 미팅관리</span></span></li>
|
||||
<li class="border-t border-gray-100 pt-1 mt-1"></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="카드 세무항목 매칭 전략 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" /></svg><span class="font-medium sidebar-text">카드 세무항목 매칭 전략</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="한국 카드사 API 보고서 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg><span class="font-medium sidebar-text">한국 카드사 API 보고서</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="카드 사용내역 수집 후 매칭 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4" /></svg><span class="font-medium sidebar-text">카드 사용내역 수집 후 매칭</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="계좌입출금 내역 조회 API (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 6l3 1m0 0l-3 9a5.002 5.002 0 006.001 0M6 7l3 9M6 7l6-2m6 2l3-1m-3 1l-3 9a5.002 5.002 0 006.001 0M18 7l3 9m-3-9l-6-2m0-2v2m0 16V5m0 16H9m3 0h3" /></svg><span class="font-medium sidebar-text">계좌입출금 내역 조회 API</span></span></li>
|
||||
<li class="border-t border-gray-100 pt-1 mt-1"></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="영업관리 시나리오 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" /></svg><span class="font-medium sidebar-text">영업관리 시나리오</span></span></li>
|
||||
<li><span class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-400 cursor-not-allowed" title="매니저 시나리오 (준비중)"><svg class="w-4 h-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" /></svg><span class="font-medium sidebar-text">매니저 시나리오</span></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 축소 상태: 아이콘 + 플라이아웃 -->
|
||||
<div class="lab-collapsed-view hidden">
|
||||
<div class="lab-flyout-trigger relative">
|
||||
<button type="button" class="flex items-center justify-center w-full p-2 rounded-lg hover:bg-amber-50 transition-colors" title="실험실">
|
||||
<svg class="w-5 h-5 text-amber-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- 플라이아웃 팝업 -->
|
||||
<div class="lab-flyout hidden absolute left-full top-0 ml-2 w-56 bg-white rounded-lg shadow-xl border border-gray-200 z-[1000]">
|
||||
<!-- 화살표 -->
|
||||
<div class="absolute -left-2 top-3 w-0 h-0 border-t-8 border-b-8 border-r-8 border-transparent border-r-white"></div>
|
||||
<div class="absolute -left-[9px] top-3 w-0 h-0 border-t-8 border-b-8 border-r-8 border-transparent border-r-gray-200"></div>
|
||||
|
||||
<!-- 헤더 -->
|
||||
<div class="px-3 py-2 bg-gradient-to-r from-amber-50 to-amber-100 rounded-t-lg border-b border-amber-200">
|
||||
<span class="text-xs font-bold text-amber-800 uppercase tracking-wider">실험실</span>
|
||||
</div>
|
||||
|
||||
<!-- 탭 -->
|
||||
<div class="flex p-2 bg-gray-50 border-b border-gray-100">
|
||||
<button type="button" onclick="switchLabFlyoutTab('s')" id="lab-flyout-tab-s" class="lab-flyout-tab active flex-1 py-1.5 text-xs font-bold rounded transition-all text-blue-600">
|
||||
S
|
||||
</button>
|
||||
<button type="button" onclick="switchLabFlyoutTab('a')" id="lab-flyout-tab-a" class="lab-flyout-tab flex-1 py-1.5 text-xs font-bold rounded transition-all text-purple-600">
|
||||
A
|
||||
</button>
|
||||
<button type="button" onclick="switchLabFlyoutTab('m')" id="lab-flyout-tab-m" class="lab-flyout-tab flex-1 py-1.5 text-xs font-bold rounded transition-all text-green-600">
|
||||
M
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 메뉴 패널들 -->
|
||||
<div class="p-2 max-h-64 overflow-y-auto">
|
||||
<!-- S. Strategy (16개) -->
|
||||
<ul id="lab-flyout-panel-s" class="lab-flyout-panel space-y-0.5">
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">세무 전략</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">노무 전략</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">채권추심 전략</span></li>
|
||||
<li class="border-t border-gray-100 my-1"></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">스테이블코인 보고서</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">MRP 해외사례</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">상담용 챗봇 전략</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">KoDATA vs NICE API</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">바로빌 vs 팝빌 API</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">사내 지식 검색 시스템</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">챗봇 솔루션 비교 분석</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">RAG 스타트업 현황</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">더존비즈온 분석</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">Confluence vs Notion</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">차세대 QA 솔루션</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">SAM 영업전략</span></li>
|
||||
</ul>
|
||||
<!-- A. AI/Automation (12개) -->
|
||||
<ul id="lab-flyout-panel-a" class="lab-flyout-panel space-y-0.5 hidden">
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">사업자등록증 OCR</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">웹 녹음 AI 요약</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">회의록 AI 요약</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">업무협의록 AI 요약</span></li>
|
||||
<li class="border-t border-gray-100 my-1"></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">운영자용 챗봇</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">Vertex RAG 챗봇</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">테넌트 지식 업로드</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">테넌트 챗봇</span></li>
|
||||
<li class="border-t border-gray-100 my-1"></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">SAM AI 메뉴 이동</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">SAM AI 알람음 제작</span></li>
|
||||
<li class="border-t border-gray-100 my-1"></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">GPS 출퇴근 관리</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">기업개황 조회</span></li>
|
||||
</ul>
|
||||
<!-- M. Management (13개) -->
|
||||
<ul id="lab-flyout-panel-m" class="lab-flyout-panel space-y-0.5 hidden">
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">바로빌 테넌트 관리</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">전자세금계산서 전략</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">전자세금계산서</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">사업자등록번호 진위 확인</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">영업관리 & 매니저 미팅</span></li>
|
||||
<li class="border-t border-gray-100 my-1"></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">카드 세무항목 매칭 전략</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">한국 카드사 API 보고서</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">카드 사용내역 수집 후 매칭</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">계좌입출금 내역 조회 API</span></li>
|
||||
<li class="border-t border-gray-100 my-1"></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">영업관리 시나리오</span></li>
|
||||
<li><span class="block px-2 py-1 text-xs text-gray-400 rounded hover:bg-gray-50">매니저 시나리오</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@@ -584,6 +767,179 @@ class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-gray-700 hover:
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* ========== 3단계 메뉴 스타일 ========== */
|
||||
|
||||
/* 서브그룹 헤더 (2단계) */
|
||||
.sidebar-subgroup-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.5rem 0.75rem;
|
||||
margin-left: 1.5rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: #6b7280;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.025em;
|
||||
cursor: pointer;
|
||||
border-radius: 0.375rem;
|
||||
transition: background-color 0.15s;
|
||||
}
|
||||
|
||||
.sidebar-subgroup-header:hover {
|
||||
background-color: #f3f4f6;
|
||||
}
|
||||
|
||||
/* 서브그룹 컨테이너 */
|
||||
.sidebar-subgroup-items {
|
||||
margin-left: 0.5rem;
|
||||
border-left: 2px solid #e5e7eb;
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
/* 3단계 메뉴 아이템 들여쓰기 */
|
||||
.sidebar-subgroup-items a,
|
||||
.sidebar-subgroup-items span {
|
||||
padding-left: 2.5rem !important;
|
||||
}
|
||||
|
||||
/* 서브그룹 아이콘 회전 */
|
||||
.sidebar-subgroup-header .subgroup-icon {
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.sidebar-subgroup-header.collapsed .subgroup-icon {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
/* 접힌 상태에서 서브그룹 헤더 숨김 */
|
||||
html.sidebar-is-collapsed #sidebar .sidebar-subgroup-header,
|
||||
.sidebar.sidebar-collapsed .sidebar-subgroup-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 접힌 상태에서 서브그룹 아이템 border 숨김 */
|
||||
html.sidebar-is-collapsed #sidebar .sidebar-subgroup-items,
|
||||
.sidebar.sidebar-collapsed .sidebar-subgroup-items {
|
||||
margin-left: 0;
|
||||
border-left: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/* 접힌 상태에서 3단계 메뉴 아이템 패딩 리셋 */
|
||||
html.sidebar-is-collapsed #sidebar .sidebar-subgroup-items a,
|
||||
html.sidebar-is-collapsed #sidebar .sidebar-subgroup-items span,
|
||||
.sidebar.sidebar-collapsed .sidebar-subgroup-items a,
|
||||
.sidebar.sidebar-collapsed .sidebar-subgroup-items span {
|
||||
padding-left: 0.75rem !important;
|
||||
}
|
||||
|
||||
/* 실험실 그룹 특별 스타일 */
|
||||
.lab-group-header {
|
||||
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
|
||||
border: 1px solid #f59e0b;
|
||||
}
|
||||
|
||||
.lab-group-header:hover {
|
||||
background: linear-gradient(135deg, #fde68a 0%, #fcd34d 100%);
|
||||
}
|
||||
|
||||
/* ========== 실험실 탭 + 플라이아웃 스타일 ========== */
|
||||
|
||||
/* 탭 버튼 스타일 */
|
||||
.lab-tabs .lab-tab {
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.lab-tabs .lab-tab.active {
|
||||
background: white;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.lab-tabs .lab-tab:not(.active):hover {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
/* 확장 상태에서 축소 뷰 숨김 */
|
||||
.lab-expanded-view {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.lab-collapsed-view {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 축소 상태에서 확장 뷰 숨김, 축소 뷰 표시 */
|
||||
html.sidebar-is-collapsed #sidebar .lab-expanded-view,
|
||||
.sidebar.sidebar-collapsed .lab-expanded-view {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
html.sidebar-is-collapsed #sidebar .lab-collapsed-view,
|
||||
.sidebar.sidebar-collapsed .lab-collapsed-view {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/* 플라이아웃 트리거 */
|
||||
.lab-flyout-trigger {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 플라이아웃 표시 (호버 시) */
|
||||
.lab-flyout-trigger:hover .lab-flyout {
|
||||
display: block !important;
|
||||
animation: flyoutFadeIn 0.15s ease-out;
|
||||
}
|
||||
|
||||
@keyframes flyoutFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 플라이아웃 탭 스타일 */
|
||||
.lab-flyout-tab {
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.lab-flyout-tab.active {
|
||||
background: white;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.lab-flyout-tab:not(.active):hover {
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
/* 접힌 상태에서 실험실 메뉴 아이템 스타일 리셋 */
|
||||
html.sidebar-is-collapsed #sidebar .lab-panel span,
|
||||
.sidebar.sidebar-collapsed .lab-panel span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 접힌 상태에서 탭 숨김 */
|
||||
html.sidebar-is-collapsed #sidebar .lab-tabs,
|
||||
.sidebar.sidebar-collapsed .lab-tabs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 접힌 상태에서 실험실 그룹 border-t 유지 */
|
||||
html.sidebar-is-collapsed #sidebar .lab-menu-container,
|
||||
.sidebar.sidebar-collapsed .lab-menu-container {
|
||||
border-top: 1px solid #e5e7eb;
|
||||
padding-top: 1rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
@@ -608,18 +964,54 @@ function toggleGroup(groupId) {
|
||||
}
|
||||
}
|
||||
|
||||
// 서브그룹 토글 함수 (3단계 메뉴용)
|
||||
function toggleSubgroup(subgroupId) {
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
// 사이드바가 접힌 상태면 서브그룹 토글 무시
|
||||
if (sidebar.classList.contains('sidebar-collapsed') || document.documentElement.classList.contains('sidebar-is-collapsed')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const subgroup = document.getElementById(subgroupId);
|
||||
const icon = document.getElementById(subgroupId + '-icon');
|
||||
const header = icon ? icon.closest('.sidebar-subgroup-header') : null;
|
||||
|
||||
if (subgroup.style.display === 'none') {
|
||||
subgroup.style.display = 'block';
|
||||
if (header) header.classList.remove('collapsed');
|
||||
localStorage.setItem('sidebar-' + subgroupId, 'open');
|
||||
} else {
|
||||
subgroup.style.display = 'none';
|
||||
if (header) header.classList.add('collapsed');
|
||||
localStorage.setItem('sidebar-' + subgroupId, 'closed');
|
||||
}
|
||||
}
|
||||
|
||||
// 페이지 로드 시 저장된 상태 복원
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
['system-group', 'permission-group', 'production-group', 'content-group', 'system-settings-group', 'pm-group', 'dev-tools-group'].forEach(function(groupId) {
|
||||
// 1단계 그룹 상태 복원
|
||||
['system-group', 'permission-group', 'production-group', 'content-group', 'system-settings-group', 'pm-group', 'dev-tools-group', 'lab-group'].forEach(function(groupId) {
|
||||
const state = localStorage.getItem('sidebar-' + groupId);
|
||||
if (state === 'closed') {
|
||||
const group = document.getElementById(groupId);
|
||||
const icon = document.getElementById(groupId + '-icon');
|
||||
group.style.display = 'none';
|
||||
icon.style.transform = 'rotate(-90deg)';
|
||||
if (group) group.style.display = 'none';
|
||||
if (icon) icon.style.transform = 'rotate(-90deg)';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 서브그룹 (2단계) 상태 복원
|
||||
['lab-s-group', 'lab-a-group', 'lab-m-group'].forEach(function(subgroupId) {
|
||||
const state = localStorage.getItem('sidebar-' + subgroupId);
|
||||
if (state === 'closed') {
|
||||
const subgroup = document.getElementById(subgroupId);
|
||||
const icon = document.getElementById(subgroupId + '-icon');
|
||||
const header = icon ? icon.closest('.sidebar-subgroup-header') : null;
|
||||
if (subgroup) subgroup.style.display = 'none';
|
||||
if (header) header.classList.add('collapsed');
|
||||
}
|
||||
});
|
||||
|
||||
// 사이드바 접힌 상태에서 메뉴 아이템 호버 시 툴팁 표시
|
||||
initSidebarTooltips();
|
||||
});
|
||||
@@ -702,4 +1094,79 @@ function initSidebarTooltips() {
|
||||
}, 150);
|
||||
});
|
||||
}
|
||||
|
||||
// ========== 실험실 탭 전환 함수 ==========
|
||||
|
||||
// 확장 상태: 탭 전환
|
||||
function switchLabTab(tabKey) {
|
||||
const tabs = ['s', 'a', 'm'];
|
||||
|
||||
// 모든 탭 버튼에서 active 제거
|
||||
tabs.forEach(function(key) {
|
||||
const tab = document.getElementById('lab-tab-' + key);
|
||||
const panel = document.getElementById('lab-panel-' + key);
|
||||
|
||||
if (tab) {
|
||||
tab.classList.remove('active');
|
||||
}
|
||||
if (panel) {
|
||||
panel.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
// 선택된 탭 활성화
|
||||
const activeTab = document.getElementById('lab-tab-' + tabKey);
|
||||
const activePanel = document.getElementById('lab-panel-' + tabKey);
|
||||
|
||||
if (activeTab) {
|
||||
activeTab.classList.add('active');
|
||||
}
|
||||
if (activePanel) {
|
||||
activePanel.classList.remove('hidden');
|
||||
}
|
||||
|
||||
// 상태 저장
|
||||
localStorage.setItem('lab-active-tab', tabKey);
|
||||
}
|
||||
|
||||
// 축소 상태 (플라이아웃): 탭 전환
|
||||
function switchLabFlyoutTab(tabKey) {
|
||||
const tabs = ['s', 'a', 'm'];
|
||||
|
||||
// 모든 탭 버튼에서 active 제거
|
||||
tabs.forEach(function(key) {
|
||||
const tab = document.getElementById('lab-flyout-tab-' + key);
|
||||
const panel = document.getElementById('lab-flyout-panel-' + key);
|
||||
|
||||
if (tab) {
|
||||
tab.classList.remove('active');
|
||||
}
|
||||
if (panel) {
|
||||
panel.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
// 선택된 탭 활성화
|
||||
const activeTab = document.getElementById('lab-flyout-tab-' + tabKey);
|
||||
const activePanel = document.getElementById('lab-flyout-panel-' + tabKey);
|
||||
|
||||
if (activeTab) {
|
||||
activeTab.classList.add('active');
|
||||
}
|
||||
if (activePanel) {
|
||||
activePanel.classList.remove('hidden');
|
||||
}
|
||||
|
||||
// 상태 저장 (확장 탭과 동기화)
|
||||
localStorage.setItem('lab-active-tab', tabKey);
|
||||
}
|
||||
|
||||
// 페이지 로드 시 저장된 탭 상태 복원
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const savedTab = localStorage.getItem('lab-active-tab');
|
||||
if (savedTab && ['s', 'a', 'm'].includes(savedTab)) {
|
||||
switchLabTab(savedTab);
|
||||
switchLabFlyoutTab(savedTab);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user