294 lines
9.2 KiB
Markdown
294 lines
9.2 KiB
Markdown
# 조건부 컨테이너 (ConditionalContainer) - 화면 선택 방식
|
|
|
|
제어 셀렉트박스 값에 따라 다른 **화면**을 표시하는 조건부 컨테이너 컴포넌트입니다.
|
|
|
|
## 📋 개요
|
|
|
|
화면 편집기에서 조건별로 표시할 화면을 선택하여 조건부 UI를 구성할 수 있는 컨테이너입니다. 상단의 셀렉트박스 값에 따라 하단에 미리 만들어진 화면을 표시합니다.
|
|
|
|
## ✨ 주요 기능
|
|
|
|
- ✅ **조건별 화면 전환**: 셀렉트박스 값에 따라 다른 화면 표시
|
|
- ✅ **화면 재사용**: 기존에 만든 화면을 조건별로 할당
|
|
- ✅ **간편한 구성**: 복잡한 입력 폼도 화면 선택으로 간단히 구성
|
|
- ✅ **자동 동기화**: 화면 수정 시 자동 반영
|
|
- ✅ **폼 데이터 연동**: formData와 자동 동기화
|
|
- ✅ **커스터마이징**: 테두리, 간격, 기본값 등 설정 가능
|
|
|
|
## 🎯 사용 사례
|
|
|
|
### 1. 입력 방식 선택
|
|
```
|
|
[셀렉트: 입력 방식]
|
|
├─ 거래처 우선: "거래처_우선_입력_화면" (화면 ID: 101)
|
|
├─ 견적서 기반: "견적서_업로드_화면" (화면 ID: 102)
|
|
└─ 단가 직접입력: "단가_직접입력_화면" (화면 ID: 103)
|
|
```
|
|
|
|
### 2. 판매 유형 선택
|
|
```
|
|
[셀렉트: 판매 유형]
|
|
├─ 국내 판매: "국내판매_기본폼" (화면 ID: 201)
|
|
└─ 해외 판매: "해외판매_무역정보폼" (화면 ID: 202)
|
|
```
|
|
|
|
### 3. 문서 유형 선택
|
|
```
|
|
[셀렉트: 문서 유형]
|
|
├─ 신규 작성: "신규문서_입력폼" (화면 ID: 301)
|
|
├─ 복사 생성: "문서복사_화면" (화면 ID: 302)
|
|
└─ 불러오기: "파일업로드_화면" (화면 ID: 303)
|
|
```
|
|
|
|
## 📐 구조
|
|
|
|
```
|
|
┌─────────────────────────────────┐
|
|
│ ConditionalContainer │
|
|
├─────────────────────────────────┤
|
|
│ [제어 셀렉트박스] │ ← controlField, controlLabel
|
|
├─────────────────────────────────┤
|
|
│ 📄 조건 1: "옵션 A" 선택 시 │ ← sections[0]
|
|
│ ┌─────────────────────────────┐│
|
|
│ │ [선택된 화면이 표시됨] ││ ← screenId로 지정된 화면
|
|
│ │ (화면 ID: 101) ││
|
|
│ │ ││
|
|
│ └─────────────────────────────┘│
|
|
├─────────────────────────────────┤
|
|
│ 📄 조건 2: "옵션 B" 선택 시 │ ← sections[1]
|
|
│ ┌─────────────────────────────┐│
|
|
│ │ [다른 화면이 표시됨] ││ ← screenId로 지정된 다른 화면
|
|
│ │ (화면 ID: 102) ││
|
|
│ └─────────────────────────────┘│
|
|
└─────────────────────────────────┘
|
|
```
|
|
|
|
## 🔧 설정 방법
|
|
|
|
### 1. 컴포넌트 추가
|
|
화면 편집기의 컴포넌트 패널에서 **"조건부 컨테이너"**를 드래그하여 캔버스에 배치합니다.
|
|
|
|
### 2. 설정 패널에서 구성
|
|
|
|
#### 제어 필드 설정
|
|
- **제어 필드명**: formData에 저장될 필드명 (예: `inputMode`)
|
|
- **셀렉트박스 라벨**: 화면에 표시될 라벨 (예: "입력 방식")
|
|
|
|
#### 조건별 섹션 추가
|
|
1. **"섹션 추가"** 버튼 클릭
|
|
2. 각 섹션 설정:
|
|
- **조건 값**: 고유한 값 (예: `customer_first`)
|
|
- **표시 라벨**: 사용자에게 보이는 텍스트 (예: "거래처 우선")
|
|
|
|
#### 기본값 설정
|
|
- 처음 화면 로드 시 선택될 기본 조건 선택
|
|
|
|
#### 스타일 설정
|
|
- **섹션 테두리 표시**: ON/OFF
|
|
- **섹션 간격**: 좁게 / 보통 / 넓게
|
|
|
|
### 3. 조건별 화면 선택
|
|
|
|
1. **디자인 모드**에서 모든 조건 섹션이 표시됩니다
|
|
2. 각 섹션의 **"표시할 화면"** 드롭다운에서 화면을 선택합니다
|
|
3. 선택된 화면 ID와 이름이 자동으로 저장됩니다
|
|
|
|
**장점:**
|
|
- ✅ 이미 만든 화면을 재사용
|
|
- ✅ 복잡한 입력 폼도 간단히 구성
|
|
- ✅ 화면 수정 시 자동 반영
|
|
|
|
### 4. 실행 모드 동작
|
|
|
|
- 셀렉트박스에서 조건 선택
|
|
- 선택된 조건의 **화면**이 표시됨
|
|
- 다른 조건의 화면은 자동으로 숨김
|
|
|
|
## 💻 기술 사양
|
|
|
|
### Props
|
|
|
|
```typescript
|
|
interface ConditionalContainerProps {
|
|
// 제어 필드
|
|
controlField: string; // 예: "inputMode"
|
|
controlLabel: string; // 예: "입력 방식"
|
|
|
|
// 조건별 섹션
|
|
sections: ConditionalSection[];
|
|
|
|
// 기본값
|
|
defaultValue?: string;
|
|
|
|
// 스타일
|
|
showBorder?: boolean; // 기본: true
|
|
spacing?: "tight" | "normal" | "loose"; // 기본: "normal"
|
|
|
|
// 폼 연동
|
|
formData?: Record<string, any>;
|
|
onFormDataChange?: (fieldName: string, value: any) => void;
|
|
}
|
|
|
|
interface ConditionalSection {
|
|
id: string; // 고유 ID
|
|
condition: string; // 조건 값
|
|
label: string; // 표시 라벨
|
|
screenId: number | null; // 표시할 화면 ID
|
|
screenName?: string; // 화면 이름 (표시용)
|
|
}
|
|
```
|
|
|
|
### 기본 설정
|
|
|
|
```typescript
|
|
defaultSize: {
|
|
width: 800,
|
|
height: 600,
|
|
}
|
|
|
|
defaultConfig: {
|
|
controlField: "condition",
|
|
controlLabel: "조건 선택",
|
|
sections: [
|
|
{
|
|
id: "section_1",
|
|
condition: "option1",
|
|
label: "옵션 1",
|
|
screenId: null, // 화면 미선택 상태
|
|
},
|
|
{
|
|
id: "section_2",
|
|
condition: "option2",
|
|
label: "옵션 2",
|
|
screenId: null, // 화면 미선택 상태
|
|
},
|
|
],
|
|
defaultValue: "option1",
|
|
showBorder: true,
|
|
spacing: "normal",
|
|
}
|
|
```
|
|
|
|
## 🎨 디자인 모드 vs 실행 모드
|
|
|
|
### 디자인 모드 (편집기)
|
|
- ✅ 모든 조건 섹션 표시
|
|
- ✅ 각 섹션에 "조건: XXX" 라벨 표시
|
|
- ✅ 화면 선택 안내 메시지 (미선택 시)
|
|
- ✅ 선택된 화면 ID 표시
|
|
- ✅ 활성 조건 "(활성)" 표시
|
|
|
|
### 실행 모드 (할당된 화면)
|
|
- ✅ 선택된 조건의 화면만 표시
|
|
- ✅ 다른 조건의 화면 자동 숨김
|
|
- ✅ 깔끔한 UI (라벨, 점선 테두리 제거)
|
|
- ✅ 선택된 화면이 완전히 통합되어 표시
|
|
|
|
## 📊 폼 데이터 연동
|
|
|
|
### 자동 동기화
|
|
```typescript
|
|
// formData 읽기
|
|
formData[controlField] // 현재 선택된 값
|
|
|
|
// formData 쓰기
|
|
onFormDataChange(controlField, newValue)
|
|
```
|
|
|
|
### 예시
|
|
```typescript
|
|
// controlField = "salesType"
|
|
formData = {
|
|
salesType: "export", // ← 자동으로 여기에 저장됨
|
|
// ... 다른 필드들
|
|
}
|
|
|
|
// 셀렉트박스 값 변경 시 자동으로 formData 업데이트
|
|
```
|
|
|
|
## 🔍 주의사항
|
|
|
|
1. **조건 값은 고유해야 함**: 각 섹션의 `condition` 값은 중복되면 안 됩니다
|
|
2. **최소 1개 섹션 필요**: 섹션이 없으면 안내 메시지 표시
|
|
3. **컴포넌트 ID 충돌 방지**: 각 섹션의 컴포넌트 ID는 전역적으로 고유해야 함
|
|
|
|
## 📝 예시: 수주 입력 방식 선택
|
|
|
|
```typescript
|
|
{
|
|
controlField: "inputMode",
|
|
controlLabel: "입력 방식",
|
|
sections: [
|
|
{
|
|
id: "customer_first",
|
|
condition: "customer_first",
|
|
label: "거래처 우선",
|
|
components: [
|
|
// 거래처 검색 컴포넌트
|
|
// 품목 선택 테이블
|
|
// 저장 버튼
|
|
]
|
|
},
|
|
{
|
|
id: "quotation",
|
|
condition: "quotation",
|
|
label: "견적서 기반",
|
|
components: [
|
|
// 견적서 검색 컴포넌트
|
|
// 견적서 내용 표시
|
|
// 수주 전환 버튼
|
|
]
|
|
},
|
|
{
|
|
id: "unit_price",
|
|
condition: "unit_price",
|
|
label: "단가 직접입력",
|
|
components: [
|
|
// 품목 입력 테이블
|
|
// 단가 입력 필드들
|
|
// 계산 위젯
|
|
]
|
|
}
|
|
],
|
|
defaultValue: "customer_first",
|
|
showBorder: true,
|
|
spacing: "normal"
|
|
}
|
|
```
|
|
|
|
## 🚀 로드맵
|
|
|
|
- [ ] 다중 제어 필드 지원 (AND/OR 조건)
|
|
- [ ] 섹션 전환 애니메이션
|
|
- [ ] 조건별 검증 규칙
|
|
- [ ] 템플릿 저장/불러오기
|
|
|
|
## 🐛 트러블슈팅
|
|
|
|
### Q: 섹션이 전환되지 않아요
|
|
A: `controlField` 값이 formData에 제대로 저장되고 있는지 확인하세요.
|
|
|
|
### Q: 컴포넌트가 드롭되지 않아요
|
|
A: 디자인 모드인지 확인하고, 드롭존 영역에 정확히 드롭하세요.
|
|
|
|
### Q: 다른 조건의 UI가 계속 보여요
|
|
A: 실행 모드로 전환했는지 확인하세요. 디자인 모드에서는 모든 조건이 표시됩니다.
|
|
|
|
## 📦 파일 구조
|
|
|
|
```
|
|
conditional-container/
|
|
├── types.ts # 타입 정의
|
|
├── ConditionalContainerComponent.tsx # 메인 컴포넌트
|
|
├── ConditionalSectionDropZone.tsx # 드롭존 컴포넌트
|
|
├── ConditionalContainerConfigPanel.tsx # 설정 패널
|
|
├── ConditionalContainerRenderer.tsx # 렌더러 및 등록
|
|
├── index.ts # 컴포넌트 정의
|
|
└── README.md # 이 파일
|
|
```
|
|
|
|
## 🎉 완료!
|
|
|
|
이제 화면 편집기에서 **조건부 컨테이너**를 사용하여 동적인 UI를 만들 수 있습니다! 🚀
|
|
|