feat: 자동 채우기 테이블 선택 드롭다운 및 동적 컬럼 로드 추가
- 추가 입력 필드에서 자동 채우기 테이블을 드롭다운으로 선택 가능 - 텍스트 입력 대신 allTables에서 선택하는 방식으로 개선 - 테이블 선택 시 해당 테이블의 컬럼을 자동으로 로드 - autoFillTableColumns 상태로 필드별 테이블 컬럼 관리 - 선택한 테이블에 따라 컬럼 드롭다운이 동적으로 변경됨 사용자 경험 개선: - 테이블명을 직접 입력하는 대신 목록에서 선택 - 선택한 테이블의 컬럼만 표시되어 혼란 방지 - 원본 테이블(기본) 또는 다른 테이블 선택 가능
This commit is contained in:
parent
6e92d1855a
commit
86eb9f0425
|
|
@ -73,6 +73,9 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
|||
// 🆕 부모 데이터 매핑: 각 매핑별 소스 테이블 컬럼 상태
|
||||
const [mappingSourceColumns, setMappingSourceColumns] = useState<Record<number, Array<{ columnName: string; columnLabel?: string; dataType?: string }>>>({});
|
||||
|
||||
// 🆕 추가 입력 필드별 자동 채우기 테이블 컬럼 상태
|
||||
const [autoFillTableColumns, setAutoFillTableColumns] = useState<Record<number, Array<{ columnName: string; columnLabel?: string; dataType?: string }>>>({});
|
||||
|
||||
// 🆕 원본/대상 테이블 컬럼 상태 (내부에서 로드)
|
||||
const [loadedSourceTableColumns, setLoadedSourceTableColumns] = useState<Array<{ columnName: string; columnLabel?: string; dataType?: string }>>([]);
|
||||
const [loadedTargetTableColumns, setLoadedTargetTableColumns] = useState<Array<{ columnName: string; columnLabel?: string; dataType?: string }>>([]);
|
||||
|
|
@ -137,6 +140,38 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
|||
loadColumns();
|
||||
}, [config.targetTable]);
|
||||
|
||||
// 🆕 자동 채우기 테이블 선택 시 컬럼 로드
|
||||
const loadAutoFillTableColumns = async (tableName: string, fieldIndex: number) => {
|
||||
if (!tableName) {
|
||||
setAutoFillTableColumns(prev => ({ ...prev, [fieldIndex]: [] }));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(`🔍 [필드 ${fieldIndex}] 자동 채우기 테이블 컬럼 로드:`, tableName);
|
||||
|
||||
const { tableManagementApi } = await import("@/lib/api/tableManagement");
|
||||
const response = await tableManagementApi.getColumnList(tableName);
|
||||
|
||||
if (response.success && response.data) {
|
||||
const columns = response.data.columns || [];
|
||||
setAutoFillTableColumns(prev => ({
|
||||
...prev,
|
||||
[fieldIndex]: columns.map((col: any) => ({
|
||||
columnName: col.columnName,
|
||||
columnLabel: col.displayName || col.columnLabel || col.columnName,
|
||||
dataType: col.dataType,
|
||||
}))
|
||||
}));
|
||||
console.log(`✅ [필드 ${fieldIndex}] 컬럼 로드 성공:`, columns.length);
|
||||
} else {
|
||||
console.error(`❌ [필드 ${fieldIndex}] 컬럼 로드 실패:`, response);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ [필드 ${fieldIndex}] 컬럼 로드 오류:`, error);
|
||||
}
|
||||
};
|
||||
|
||||
// 🆕 소스 테이블 선택 시 컬럼 로드
|
||||
const loadMappingSourceColumns = async (tableName: string, mappingIndex: number) => {
|
||||
try {
|
||||
|
|
@ -745,15 +780,66 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
|||
<div className="space-y-2">
|
||||
<Label className="text-[10px] sm:text-xs">자동 채우기 (선택)</Label>
|
||||
|
||||
{/* 테이블명 입력 */}
|
||||
<Input
|
||||
value={field.autoFillFromTable || ""}
|
||||
onChange={(e) => updateField(index, { autoFillFromTable: e.target.value })}
|
||||
placeholder="비워두면 주 데이터 (예: item_price)"
|
||||
className="h-6 w-full text-[10px] sm:h-7 sm:text-xs"
|
||||
/>
|
||||
{/* 테이블 선택 드롭다운 */}
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
className="h-6 w-full justify-between text-[10px] sm:h-7 sm:text-xs"
|
||||
>
|
||||
{field.autoFillFromTable
|
||||
? allTables.find(t => t.tableName === field.autoFillFromTable)?.displayName || field.autoFillFromTable
|
||||
: "원본 테이블 (기본)"}
|
||||
<ChevronsUpDown className="ml-1 h-2 w-2 shrink-0 opacity-50 sm:h-3 sm:w-3" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[250px] p-0 sm:w-[300px]">
|
||||
<Command>
|
||||
<CommandInput placeholder="테이블 검색..." className="h-6 text-[10px] sm:h-7 sm:text-xs" />
|
||||
<CommandEmpty className="text-[10px] sm:text-xs">테이블을 찾을 수 없습니다.</CommandEmpty>
|
||||
<CommandGroup className="max-h-[200px] overflow-auto">
|
||||
<CommandItem
|
||||
value=""
|
||||
onSelect={() => {
|
||||
updateField(index, { autoFillFromTable: undefined, autoFillFrom: undefined });
|
||||
setAutoFillTableColumns(prev => ({ ...prev, [index]: [] }));
|
||||
}}
|
||||
className="text-[10px] sm:text-xs"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-1 h-2 w-2 sm:mr-2 sm:h-3 sm:w-3",
|
||||
!field.autoFillFromTable ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
원본 테이블 ({config.sourceTable || "미설정"})
|
||||
</CommandItem>
|
||||
{allTables.map((table) => (
|
||||
<CommandItem
|
||||
key={table.tableName}
|
||||
value={table.tableName}
|
||||
onSelect={(value) => {
|
||||
updateField(index, { autoFillFromTable: value, autoFillFrom: undefined });
|
||||
loadAutoFillTableColumns(value, index);
|
||||
}}
|
||||
className="text-[10px] sm:text-xs"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-1 h-2 w-2 sm:mr-2 sm:h-3 sm:w-3",
|
||||
field.autoFillFromTable === table.tableName ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{table.displayName || table.tableName}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<p className="text-[9px] text-gray-500 sm:text-[10px]">
|
||||
다른 테이블에서 가져올 경우 테이블명 입력
|
||||
다른 테이블에서 가져올 경우 테이블 선택
|
||||
</p>
|
||||
|
||||
{/* 필드 선택 */}
|
||||
|
|
@ -764,16 +850,26 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
|||
role="combobox"
|
||||
className="h-6 w-full justify-between text-[10px] sm:h-7 sm:text-xs"
|
||||
>
|
||||
{field.autoFillFrom
|
||||
? sourceTableColumns.find(c => c.columnName === field.autoFillFrom)?.columnLabel || field.autoFillFrom
|
||||
: "필드 선택 안 함"}
|
||||
{(() => {
|
||||
if (!field.autoFillFrom) return "필드 선택 안 함";
|
||||
|
||||
// 선택된 테이블의 컬럼에서 찾기
|
||||
const columns = field.autoFillFromTable
|
||||
? (autoFillTableColumns[index] || [])
|
||||
: (loadedSourceTableColumns.length > 0 ? loadedSourceTableColumns : sourceTableColumns);
|
||||
|
||||
const found = columns.find(c => c.columnName === field.autoFillFrom);
|
||||
return found?.columnLabel || field.autoFillFrom;
|
||||
})()}
|
||||
<ChevronsUpDown className="ml-1 h-2 w-2 shrink-0 opacity-50 sm:h-3 sm:w-3" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[180px] p-0 sm:w-[200px]">
|
||||
<Command>
|
||||
<CommandInput placeholder="컬럼 검색..." className="h-6 text-[10px] sm:h-7 sm:text-xs" />
|
||||
<CommandEmpty className="text-[10px] sm:text-xs">원본 테이블을 먼저 선택하세요.</CommandEmpty>
|
||||
<CommandEmpty className="text-[10px] sm:text-xs">
|
||||
{field.autoFillFromTable ? "컬럼을 찾을 수 없습니다" : "원본 테이블을 먼저 선택하세요"}
|
||||
</CommandEmpty>
|
||||
<CommandGroup className="max-h-[150px] overflow-auto sm:max-h-[200px]">
|
||||
<CommandItem
|
||||
value=""
|
||||
|
|
@ -788,25 +884,32 @@ export const SelectedItemsDetailInputConfigPanel: React.FC<SelectedItemsDetailIn
|
|||
/>
|
||||
선택 안 함
|
||||
</CommandItem>
|
||||
{sourceTableColumns.map((column) => (
|
||||
<CommandItem
|
||||
key={column.columnName}
|
||||
value={column.columnName}
|
||||
onSelect={() => updateField(index, { autoFillFrom: column.columnName })}
|
||||
className="text-[10px] sm:text-xs"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-1 h-2 w-2 sm:mr-2 sm:h-3 sm:w-3",
|
||||
field.autoFillFrom === column.columnName ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
<div>
|
||||
<div className="font-medium">{column.columnLabel}</div>
|
||||
<div className="text-[9px] text-gray-500">{column.columnName}</div>
|
||||
</div>
|
||||
</CommandItem>
|
||||
))}
|
||||
{(() => {
|
||||
// 선택된 테이블의 컬럼 또는 기본 원본 테이블 컬럼
|
||||
const columns = field.autoFillFromTable
|
||||
? (autoFillTableColumns[index] || [])
|
||||
: (loadedSourceTableColumns.length > 0 ? loadedSourceTableColumns : sourceTableColumns);
|
||||
|
||||
return columns.map((column) => (
|
||||
<CommandItem
|
||||
key={column.columnName}
|
||||
value={column.columnName}
|
||||
onSelect={(value) => updateField(index, { autoFillFrom: value })}
|
||||
className="text-[10px] sm:text-xs"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-1 h-2 w-2 sm:mr-2 sm:h-3 sm:w-3",
|
||||
field.autoFillFrom === column.columnName ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
<div>
|
||||
<div className="font-medium">{column.columnLabel || column.columnName}</div>
|
||||
{column.dataType && <div className="text-[8px] text-gray-500">{column.dataType}</div>}
|
||||
</div>
|
||||
</CommandItem>
|
||||
));
|
||||
})()}
|
||||
</CommandGroup>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
|
|
|
|||
Loading…
Reference in New Issue