자동완성 검색 입력 컴포넌트 다중 컬럼 표시 기능추가
This commit is contained in:
@@ -184,52 +184,118 @@ export function AutocompleteSearchInputConfigPanel({
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
{/* 2. 표시 필드 선택 */}
|
||||
{/* 2. 표시 필드 선택 (다중 선택 가능) */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs font-semibold sm:text-sm">2. 표시 필드 *</Label>
|
||||
<Popover open={openDisplayFieldCombo} onOpenChange={setOpenDisplayFieldCombo}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={openDisplayFieldCombo}
|
||||
className="h-8 w-full justify-between text-xs sm:h-10 sm:text-sm"
|
||||
disabled={!localConfig.tableName || isLoadingSourceColumns}
|
||||
>
|
||||
{localConfig.displayField
|
||||
? sourceTableColumns.find((c) => c.columnName === localConfig.displayField)?.displayName || localConfig.displayField
|
||||
: isLoadingSourceColumns ? "로딩 중..." : "사용자에게 보여줄 필드"}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="p-0" style={{ width: "var(--radix-popover-trigger-width)" }} align="start">
|
||||
<Command>
|
||||
<CommandInput placeholder="필드 검색..." className="text-xs sm:text-sm" />
|
||||
<CommandList>
|
||||
<CommandEmpty className="text-xs sm:text-sm">필드를 찾을 수 없습니다.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{sourceTableColumns.map((column) => (
|
||||
<CommandItem
|
||||
key={column.columnName}
|
||||
value={column.columnName}
|
||||
onSelect={() => {
|
||||
updateConfig({ displayField: column.columnName });
|
||||
setOpenDisplayFieldCombo(false);
|
||||
<Label className="text-xs font-semibold sm:text-sm">2. 표시 필드 * (여러 개 선택 가능)</Label>
|
||||
<div className="space-y-2">
|
||||
{/* 선택된 필드 표시 */}
|
||||
{(localConfig.displayFields && localConfig.displayFields.length > 0) ? (
|
||||
<div className="flex flex-wrap gap-1 rounded-md border p-2 min-h-[40px]">
|
||||
{localConfig.displayFields.map((fieldName) => {
|
||||
const col = sourceTableColumns.find((c) => c.columnName === fieldName);
|
||||
return (
|
||||
<span
|
||||
key={fieldName}
|
||||
className="inline-flex items-center gap-1 rounded-md bg-primary/10 px-2 py-1 text-xs"
|
||||
>
|
||||
{col?.displayName || fieldName}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const newFields = localConfig.displayFields?.filter((f) => f !== fieldName) || [];
|
||||
updateConfig({
|
||||
displayFields: newFields,
|
||||
displayField: newFields[0] || "", // 첫 번째 필드를 기본 displayField로
|
||||
});
|
||||
}}
|
||||
className="text-xs sm:text-sm"
|
||||
className="hover:text-destructive"
|
||||
>
|
||||
<Check className={cn("mr-2 h-4 w-4", localConfig.displayField === column.columnName ? "opacity-100" : "opacity-0")} />
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">{column.displayName || column.columnName}</span>
|
||||
{column.displayName && <span className="text-[10px] text-gray-500">{column.columnName}</span>}
|
||||
</div>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<X className="h-3 w-3" />
|
||||
</button>
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded-md border border-dashed p-2 text-center text-xs text-muted-foreground">
|
||||
아래에서 표시할 필드를 선택하세요
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 필드 선택 드롭다운 */}
|
||||
<Popover open={openDisplayFieldCombo} onOpenChange={setOpenDisplayFieldCombo}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={openDisplayFieldCombo}
|
||||
className="h-8 w-full justify-between text-xs sm:h-10 sm:text-sm"
|
||||
disabled={!localConfig.tableName || isLoadingSourceColumns}
|
||||
>
|
||||
{isLoadingSourceColumns ? "로딩 중..." : "필드 추가..."}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="p-0" style={{ width: "var(--radix-popover-trigger-width)" }} align="start">
|
||||
<Command>
|
||||
<CommandInput placeholder="필드 검색..." className="text-xs sm:text-sm" />
|
||||
<CommandList>
|
||||
<CommandEmpty className="text-xs sm:text-sm">필드를 찾을 수 없습니다.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{sourceTableColumns.map((column) => {
|
||||
const isSelected = localConfig.displayFields?.includes(column.columnName);
|
||||
return (
|
||||
<CommandItem
|
||||
key={column.columnName}
|
||||
value={column.columnName}
|
||||
onSelect={() => {
|
||||
const currentFields = localConfig.displayFields || [];
|
||||
let newFields: string[];
|
||||
if (isSelected) {
|
||||
newFields = currentFields.filter((f) => f !== column.columnName);
|
||||
} else {
|
||||
newFields = [...currentFields, column.columnName];
|
||||
}
|
||||
updateConfig({
|
||||
displayFields: newFields,
|
||||
displayField: newFields[0] || "", // 첫 번째 필드를 기본 displayField로
|
||||
});
|
||||
}}
|
||||
className="text-xs sm:text-sm"
|
||||
>
|
||||
<Check className={cn("mr-2 h-4 w-4", isSelected ? "opacity-100" : "opacity-0")} />
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">{column.displayName || column.columnName}</span>
|
||||
{column.displayName && <span className="text-[10px] text-gray-500">{column.columnName}</span>}
|
||||
</div>
|
||||
</CommandItem>
|
||||
);
|
||||
})}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
{/* 구분자 설정 */}
|
||||
{localConfig.displayFields && localConfig.displayFields.length > 1 && (
|
||||
<div className="flex items-center gap-2">
|
||||
<Label className="text-xs whitespace-nowrap">구분자:</Label>
|
||||
<Input
|
||||
value={localConfig.displaySeparator || " → "}
|
||||
onChange={(e) => updateConfig({ displaySeparator: e.target.value })}
|
||||
placeholder=" → "
|
||||
className="h-7 w-20 text-xs text-center"
|
||||
/>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
미리보기: {localConfig.displayFields.map((f) => {
|
||||
const col = sourceTableColumns.find((c) => c.columnName === f);
|
||||
return col?.displayName || f;
|
||||
}).join(localConfig.displaySeparator || " → ")}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 3. 저장 대상 테이블 선택 */}
|
||||
@@ -419,7 +485,9 @@ export function AutocompleteSearchInputConfigPanel({
|
||||
<strong>외부 테이블:</strong> {localConfig.tableName}
|
||||
</p>
|
||||
<p>
|
||||
<strong>표시 필드:</strong> {localConfig.displayField}
|
||||
<strong>표시 필드:</strong> {localConfig.displayFields?.length
|
||||
? localConfig.displayFields.join(localConfig.displaySeparator || " → ")
|
||||
: localConfig.displayField}
|
||||
</p>
|
||||
<p>
|
||||
<strong>저장 테이블:</strong> {localConfig.targetTable}
|
||||
|
||||
Reference in New Issue
Block a user