From 1bbce43ec1c17fd046d9e186fecb83a0ac3be5c1 Mon Sep 17 00:00:00 2001 From: DDD1542 Date: Wed, 11 Mar 2026 21:51:37 +0900 Subject: [PATCH] [agent-pipeline] pipe-20260311124806-lfrk round-1 --- .../v2/config-panels/V2InputConfigPanel.tsx | 682 +++++++++--------- 1 file changed, 343 insertions(+), 339 deletions(-) diff --git a/frontend/components/v2/config-panels/V2InputConfigPanel.tsx b/frontend/components/v2/config-panels/V2InputConfigPanel.tsx index 65157fd7..de1f32e6 100644 --- a/frontend/components/v2/config-panels/V2InputConfigPanel.tsx +++ b/frontend/components/v2/config-panels/V2InputConfigPanel.tsx @@ -2,14 +2,17 @@ /** * V2Input 설정 패널 - * 통합 입력 컴포넌트의 세부 설정을 관리합니다. + * 토스식 단계별 UX: 기본 설정 -> 타입별 설정 -> 고급 설정(접힘) */ import React, { useState, useEffect } from "react"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { Checkbox } from "@/components/ui/checkbox"; +import { Switch } from "@/components/ui/switch"; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; +import { Settings, ChevronDown, Loader2 } from "lucide-react"; +import { cn } from "@/lib/utils"; import { AutoGenerationType, AutoGenerationConfig } from "@/types/screen"; import { AutoGenerationUtils } from "@/lib/utils/autoGeneration"; import { getAvailableNumberingRules } from "@/lib/api/numberingRule"; @@ -29,6 +32,7 @@ export const V2InputConfigPanel: React.FC = ({ config, const [selectedMenuObjid, setSelectedMenuObjid] = useState(() => { return config.autoGeneration?.selectedMenuObjid || menuObjid; }); + const [advancedOpen, setAdvancedOpen] = useState(false); const updateConfig = (field: string, value: any) => { onChange({ ...config, [field]: value }); @@ -76,400 +80,400 @@ export const V2InputConfigPanel: React.FC = ({ config, loadRules(); }, [selectedMenuObjid, config.autoGeneration?.type]); + const inputType = config.inputType || config.type || "text"; + return ( -
- {/* INPUT TYPE 섹션 */} -
-

INPUT TYPE

-
- 입력 타입 -
- -
-
+
+ {/* ─── 1단계: 입력 타입 선택 ─── */} +
+

입력 타입

+ +

입력 필드의 종류를 선택해요

- {/* NUMBERING 섹션 - 채번 타입 전용 */} - {config.inputType === "numbering" && ( -
-

NUMBERING

-
-

- 채번 규칙은 테이블 관리에서 컬럼별로 설정됩니다. - 화면에 배치된 컬럼의 채번 규칙이 자동으로 적용됩니다. + {/* ─── 채번 타입 전용 안내 ─── */} + {inputType === "numbering" && ( +

+
+

+ 채번 규칙은 테이블 관리에서 컬럼별로 설정돼요. + 화면에 배치된 컬럼의 채번 규칙이 자동으로 적용돼요.

-
- 읽기전용 (권장) - +
+

읽기전용

+

채번 필드는 자동 생성되므로 읽기전용을 권장해요

+
+ updateConfig("readonly", checked)} />
-

- 채번 필드는 자동으로 생성되므로 읽기전용을 권장합니다 -

)} - {/* 채번 타입이 아닌 경우에만 추가 설정 표시 */} - {config.inputType !== "numbering" && ( + {/* ─── 채번 타입이 아닌 경우: 기본 설정 ─── */} + {inputType !== "numbering" && ( <> - {/* FORMAT 섹션 */} - {(config.inputType === "text" || !config.inputType) && ( -
-

FORMAT

-
- 입력 형식 -
- -
-
-
- )} - - {/* PLACEHOLDER 섹션 */} -
-

PLACEHOLDER

-
+ {/* 기본 설정 영역 */} +
+ {/* 안내 텍스트 (placeholder) */} +
안내 텍스트 -
- updateConfig("placeholder", e.target.value)} - placeholder="입력 안내" - className="h-7 text-xs" - /> -
-
-
- - {/* RANGE 섹션 - 숫자/슬라이더 전용 */} - {(config.inputType === "number" || config.inputType === "slider") && ( -
-

RANGE

-
-
- - updateConfig("min", e.target.value ? Number(e.target.value) : undefined)} - placeholder="0" - className="h-7 text-xs" - /> -
-
- - updateConfig("max", e.target.value ? Number(e.target.value) : undefined)} - placeholder="100" - className="h-7 text-xs" - /> -
-
- - updateConfig("step", e.target.value ? Number(e.target.value) : undefined)} - placeholder="1" - className="h-7 text-xs" - /> -
-
-
- )} - - {/* TEXTAREA 섹션 */} - {config.inputType === "textarea" && ( -
-

TEXTAREA

-
- 줄 수 -
- updateConfig("rows", parseInt(e.target.value) || 3)} - min={2} - max={20} - className="h-7 text-xs" - /> -
-
-
- )} - - {/* INPUT MASK 섹션 */} -
-

INPUT MASK

-
- 마스크 -
- updateConfig("mask", e.target.value)} - placeholder="###-####-####" - className="h-7 text-xs" - /> -
-
-

# = 숫자, A = 문자, * = 모든 문자

-
- - {/* AUTO GENERATION 섹션 */} -
-

AUTO GENERATION

-
- 자동생성 활성화 - { - const currentConfig = config.autoGeneration || { type: "none", enabled: false }; - updateConfig("autoGeneration", { - ...currentConfig, - enabled: checked as boolean, - }); - }} + updateConfig("placeholder", e.target.value)} + placeholder="입력 안내" + className="h-7 w-[160px] text-xs" />
- {config.autoGeneration?.enabled && ( -
- {/* 자동생성 타입 */} -
- 타입 -
- + {/* 입력 형식 - 텍스트 타입 전용 */} + {(inputType === "text" || !config.inputType) && ( +
+ 입력 형식 + +
+ )} + + {/* 입력 마스크 */} +
+
+ 입력 마스크 +

# = 숫자, A = 문자, * = 모두

+
+ updateConfig("mask", e.target.value)} + placeholder="###-####-####" + className="h-7 w-[160px] text-xs" + /> +
+ + {/* 숫자/슬라이더: 범위 설정 */} + {(inputType === "number" || inputType === "slider") && ( +
+

값 범위

+
+
+ + updateConfig("min", e.target.value ? Number(e.target.value) : undefined)} + placeholder="0" + className="h-7 text-xs" + /> +
+
+ + updateConfig("max", e.target.value ? Number(e.target.value) : undefined)} + placeholder="100" + className="h-7 text-xs" + /> +
+
+ + updateConfig("step", e.target.value ? Number(e.target.value) : undefined)} + placeholder="1" + className="h-7 text-xs" + />
+
+ )} - {config.autoGeneration?.type && config.autoGeneration.type !== "none" && ( -

- {AutoGenerationUtils.getTypeDescription(config.autoGeneration.type)} -

- )} + {/* 여러 줄 텍스트: 줄 수 */} + {inputType === "textarea" && ( +
+ 줄 수 + updateConfig("rows", parseInt(e.target.value) || 3)} + min={2} + max={20} + className="h-7 w-[160px] text-xs" + /> +
+ )} +
- {/* 채번 규칙 선택 */} - {config.autoGeneration?.type === "numbering_rule" && ( -
-
- - 대상 메뉴 * - -
- -
+ {/* ─── 고급 설정: 자동 생성 (Collapsible) ─── */} + + + + + +
+ {/* 자동 생성 토글 */} +
+
+

자동 생성

+

값이 자동으로 채워져요

+
+ { + const currentConfig = config.autoGeneration || { type: "none", enabled: false }; + updateConfig("autoGeneration", { + ...currentConfig, + enabled: checked as boolean, + }); + }} + /> +
+ + {config.autoGeneration?.enabled && ( +
+ {/* 자동 생성 타입 */} +
+

생성 방식

+
- {selectedMenuObjid ? ( -
- - 채번 규칙 * - -
+ {config.autoGeneration?.type && config.autoGeneration.type !== "none" && ( +

+ {AutoGenerationUtils.getTypeDescription(config.autoGeneration.type)} +

+ )} + + {/* 채번 규칙 선택 */} + {config.autoGeneration?.type === "numbering_rule" && ( +
+
+

+ 대상 메뉴 * +

-
- ) : ( -
- 먼저 대상 메뉴를 선택하세요 + + {selectedMenuObjid ? ( +
+

+ 채번 규칙 * +

+ {loadingRules ? ( +
+ + 규칙 로딩 중... +
+ ) : ( + + )} +
+ ) : ( +
+ 먼저 대상 메뉴를 선택하세요 +
+ )}
)} -
- )} - {/* 자동생성 옵션 (랜덤/순차용) */} - {config.autoGeneration?.type && - ["random_string", "random_number", "sequence"].includes(config.autoGeneration.type) && ( -
- {["random_string", "random_number"].includes(config.autoGeneration.type) && ( -
- 길이 -
+ {/* 랜덤/순차 옵션 */} + {config.autoGeneration?.type && + ["random_string", "random_number", "sequence"].includes(config.autoGeneration.type) && ( +
+ {["random_string", "random_number"].includes(config.autoGeneration.type) && ( +
+ 길이 + { + updateConfig("autoGeneration", { + ...config.autoGeneration, + options: { + ...config.autoGeneration?.options, + length: parseInt(e.target.value) || 8, + }, + }); + }} + className="h-7 w-[120px] text-xs" + /> +
+ )} + +
+ 접두사 { updateConfig("autoGeneration", { ...config.autoGeneration, options: { ...config.autoGeneration?.options, - length: parseInt(e.target.value) || 8, + prefix: e.target.value, }, }); }} - className="h-7 text-xs" + placeholder="예: INV-" + className="h-7 w-[120px] text-xs" />
+ +
+ 접미사 + { + updateConfig("autoGeneration", { + ...config.autoGeneration, + options: { + ...config.autoGeneration?.options, + suffix: e.target.value, + }, + }); + }} + className="h-7 w-[120px] text-xs" + /> +
+ +
+ 미리보기 +
+ {AutoGenerationUtils.generatePreviewValue(config.autoGeneration)} +
+
)} - -
- 접두사 -
- { - updateConfig("autoGeneration", { - ...config.autoGeneration, - options: { - ...config.autoGeneration?.options, - prefix: e.target.value, - }, - }); - }} - placeholder="예: INV-" - className="h-7 text-xs" - /> -
-
- -
- 접미사 -
- { - updateConfig("autoGeneration", { - ...config.autoGeneration, - options: { - ...config.autoGeneration?.options, - suffix: e.target.value, - }, - }); - }} - className="h-7 text-xs" - /> -
-
- -
- 미리보기 -
- {AutoGenerationUtils.generatePreviewValue(config.autoGeneration)} -
-
-
- )} +
+ )}
- )} -
+ + )}