ERP-node/frontend/lib/registry/components/conditional-container/README.md

9.2 KiB

조건부 컨테이너 (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

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;         // 화면 이름 (표시용)
}

기본 설정

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 (라벨, 점선 테두리 제거)
  • 선택된 화면이 완전히 통합되어 표시

📊 폼 데이터 연동

자동 동기화

// formData 읽기
formData[controlField] // 현재 선택된 값

// formData 쓰기
onFormDataChange(controlField, newValue)

예시

// controlField = "salesType"
formData = {
  salesType: "export",  // ← 자동으로 여기에 저장됨
  // ... 다른 필드들
}

// 셀렉트박스 값 변경 시 자동으로 formData 업데이트

🔍 주의사항

  1. 조건 값은 고유해야 함: 각 섹션의 condition 값은 중복되면 안 됩니다
  2. 최소 1개 섹션 필요: 섹션이 없으면 안내 메시지 표시
  3. 컴포넌트 ID 충돌 방지: 각 섹션의 컴포넌트 ID는 전역적으로 고유해야 함

📝 예시: 수주 입력 방식 선택

{
  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를 만들 수 있습니다! 🚀