feat(ModalRepeaterTable): 항목 검색 모달 컬럼 라벨 설정 기능 추가

- sourceColumnLabels 타입 정의 (Record<string, string>)

- ConfigPanel에 소스 컬럼별 표시 라벨 입력 UI 추가

- columnLabels 생성 시 sourceColumnLabels 우선 적용

- 컬럼 삭제 시 해당 라벨도 함께 삭제

- 빈 상태 안내 메시지 추가
This commit is contained in:
SeongHyun Kim 2025-12-08 15:34:19 +09:00
parent 892278853c
commit 61c1f10495
3 changed files with 68 additions and 25 deletions

View File

@ -185,6 +185,9 @@ export function ModalRepeaterTableComponent({
const rawSourceColumns = componentConfig?.sourceColumns || propSourceColumns || []; const rawSourceColumns = componentConfig?.sourceColumns || propSourceColumns || [];
const sourceColumns = rawSourceColumns.filter((col: string) => col && col.trim() !== ""); const sourceColumns = rawSourceColumns.filter((col: string) => col && col.trim() !== "");
// 모달 컬럼 라벨 (컬럼명 -> 표시 라벨)
const sourceColumnLabels = componentConfig?.sourceColumnLabels || {};
const sourceSearchFields = componentConfig?.sourceSearchFields || propSourceSearchFields || []; const sourceSearchFields = componentConfig?.sourceSearchFields || propSourceSearchFields || [];
const modalTitle = componentConfig?.modalTitle || propModalTitle || "항목 검색"; const modalTitle = componentConfig?.modalTitle || propModalTitle || "항목 검색";
const modalButtonText = componentConfig?.modalButtonText || propModalButtonText || "품목 검색"; const modalButtonText = componentConfig?.modalButtonText || propModalButtonText || "품목 검색";
@ -546,11 +549,12 @@ export function ModalRepeaterTableComponent({
handleChange(newData); handleChange(newData);
}; };
// 컬럼명 -> 라벨명 매핑 생성 // 컬럼명 -> 라벨명 매핑 생성 (sourceColumnLabels 우선, 없으면 columns에서 가져옴)
const columnLabels = columns.reduce((acc, col) => { const columnLabels = columns.reduce((acc, col) => {
acc[col.field] = col.label; // sourceColumnLabels에 정의된 라벨 우선 사용
acc[col.field] = sourceColumnLabels[col.field] || col.label;
return acc; return acc;
}, {} as Record<string, string>); }, { ...sourceColumnLabels } as Record<string, string>);
return ( return (
<div className={cn("space-y-4", className)}> <div className={cn("space-y-4", className)}>

View File

@ -520,7 +520,7 @@ export function ModalRepeaterTableConfigPanel({
{/* 소스 컬럼 */} {/* 소스 컬럼 */}
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<Label className="text-xs sm:text-sm"> </Label> <Label className="text-xs sm:text-sm"> ( )</Label>
<Button <Button
size="sm" size="sm"
variant="outline" variant="outline"
@ -533,37 +533,75 @@ export function ModalRepeaterTableConfigPanel({
</Button> </Button>
</div> </div>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
</p> </p>
<div className="space-y-2"> <div className="space-y-3">
{(localConfig.sourceColumns || []).map((column, index) => ( {(localConfig.sourceColumns || []).map((column, index) => (
<div key={index} className="flex items-center gap-2"> <div key={index} className="flex items-start gap-2 p-3 border rounded-md bg-background">
<Select <div className="flex-1 space-y-2">
value={column} {/* 컬럼 선택 */}
onValueChange={(value) => updateSourceColumn(index, value)} <div className="space-y-1">
disabled={!localConfig.sourceTable || isLoadingColumns} <Label className="text-[10px] text-muted-foreground"></Label>
> <Select
<SelectTrigger className="h-8 text-xs sm:h-10 sm:text-sm flex-1"> value={column}
<SelectValue placeholder="컬럼 선택" /> onValueChange={(value) => updateSourceColumn(index, value)}
</SelectTrigger> disabled={!localConfig.sourceTable || isLoadingColumns}
<SelectContent> >
{tableColumns.map((col) => ( <SelectTrigger className="h-8 text-xs">
<SelectItem key={col.columnName} value={col.columnName}> <SelectValue placeholder="컬럼 선택" />
{col.displayName || col.columnName} </SelectTrigger>
</SelectItem> <SelectContent>
))} {tableColumns.map((col) => (
</SelectContent> <SelectItem key={col.columnName} value={col.columnName}>
</Select> {col.displayName || col.columnName}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{/* 라벨 입력 */}
<div className="space-y-1">
<Label className="text-[10px] text-muted-foreground"> </Label>
<Input
value={localConfig.sourceColumnLabels?.[column] || ""}
onChange={(e) => {
const newLabels = { ...(localConfig.sourceColumnLabels || {}) };
if (e.target.value) {
newLabels[column] = e.target.value;
} else {
delete newLabels[column];
}
updateConfig({ sourceColumnLabels: newLabels });
}}
placeholder={tableColumns.find(c => c.columnName === column)?.displayName || column || "라벨 입력"}
className="h-8 text-xs"
disabled={!column}
/>
</div>
</div>
<Button <Button
size="sm" size="sm"
variant="ghost" variant="ghost"
onClick={() => removeSourceColumn(index)} onClick={() => {
className="h-8 w-8 p-0" // 컬럼 삭제 시 해당 라벨도 삭제
const newLabels = { ...(localConfig.sourceColumnLabels || {}) };
delete newLabels[column];
updateConfig({ sourceColumnLabels: newLabels });
removeSourceColumn(index);
}}
className="h-8 w-8 p-0 mt-5"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</Button> </Button>
</div> </div>
))} ))}
{(localConfig.sourceColumns || []).length === 0 && (
<div className="text-center py-4 border-2 border-dashed rounded-lg">
<p className="text-xs text-muted-foreground">
"추가"
</p>
</div>
)}
</div> </div>
</div> </div>

View File

@ -7,6 +7,7 @@ export interface ModalRepeaterTableProps {
// 소스 데이터 (모달에서 가져올 데이터) // 소스 데이터 (모달에서 가져올 데이터)
sourceTable: string; // 검색할 테이블 (예: "item_info") sourceTable: string; // 검색할 테이블 (예: "item_info")
sourceColumns: string[]; // 모달에 표시할 컬럼들 sourceColumns: string[]; // 모달에 표시할 컬럼들
sourceColumnLabels?: Record<string, string>; // 모달 컬럼 라벨 (컬럼명 -> 표시 라벨)
sourceSearchFields?: string[]; // 검색 가능한 필드들 sourceSearchFields?: string[]; // 검색 가능한 필드들
// 🆕 저장 대상 테이블 설정 // 🆕 저장 대상 테이블 설정