398 lines
13 KiB
TypeScript
398 lines
13 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
import { CustomerItemMappingConfig } from "./types";
|
|
import { tableTypeApi } from "@/lib/api/screen";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select";
|
|
import { Plus, X } from "lucide-react";
|
|
|
|
export interface CustomerItemMappingConfigPanelProps {
|
|
config: CustomerItemMappingConfig;
|
|
onChange: (config: CustomerItemMappingConfig) => void;
|
|
onConfigChange?: (config: CustomerItemMappingConfig) => void;
|
|
screenTableName?: string;
|
|
tableColumns?: any[];
|
|
tables?: any[];
|
|
allTables?: any[];
|
|
onTableChange?: (tableName: string) => void;
|
|
menuObjid?: number;
|
|
}
|
|
|
|
export const CustomerItemMappingConfigPanel: React.FC<
|
|
CustomerItemMappingConfigPanelProps
|
|
> = ({
|
|
config,
|
|
onChange,
|
|
onConfigChange,
|
|
screenTableName,
|
|
tableColumns: propTableColumns,
|
|
tables: propTables,
|
|
allTables,
|
|
onTableChange: propOnTableChange,
|
|
menuObjid,
|
|
}) => {
|
|
// onChange와 onConfigChange를 통합
|
|
const handleChange = (newConfig: CustomerItemMappingConfig) => {
|
|
onChange?.(newConfig);
|
|
onConfigChange?.(newConfig);
|
|
};
|
|
const [tables, setTables] = useState<any[]>([]);
|
|
const [availableColumns, setAvailableColumns] = useState<any[]>([]);
|
|
|
|
// 테이블 목록 로드
|
|
useEffect(() => {
|
|
const loadTables = async () => {
|
|
try {
|
|
const tableList = await tableTypeApi.getTables();
|
|
setTables(tableList);
|
|
} catch (error) {
|
|
console.error("테이블 목록 로드 실패:", error);
|
|
}
|
|
};
|
|
loadTables();
|
|
}, []);
|
|
|
|
// 선택된 테이블의 컬럼 목록 로드
|
|
useEffect(() => {
|
|
if (config.selectedTable) {
|
|
const loadColumns = async () => {
|
|
try {
|
|
const columns = await tableTypeApi.getColumns(config.selectedTable!);
|
|
setAvailableColumns(columns);
|
|
} catch (error) {
|
|
console.error("컬럼 목록 로드 실패:", error);
|
|
}
|
|
};
|
|
loadColumns();
|
|
}
|
|
}, [config.selectedTable]);
|
|
|
|
const handleTableChange = (tableName: string) => {
|
|
const newConfig = {
|
|
...config,
|
|
selectedTable: tableName,
|
|
columns: [], // 테이블 변경 시 컬럼 초기화
|
|
};
|
|
handleChange(newConfig);
|
|
propOnTableChange?.(tableName);
|
|
};
|
|
|
|
const handleAddColumn = (columnName: string) => {
|
|
if (!config.columns.includes(columnName)) {
|
|
handleChange({
|
|
...config,
|
|
columns: [...config.columns, columnName],
|
|
});
|
|
}
|
|
};
|
|
|
|
const handleRemoveColumn = (columnName: string) => {
|
|
handleChange({
|
|
...config,
|
|
columns: config.columns.filter((col) => col !== columnName),
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6 p-4">
|
|
{/* 테이블 선택 */}
|
|
<div className="space-y-2">
|
|
<Label>테이블 선택</Label>
|
|
<Select value={config.selectedTable} onValueChange={handleTableChange}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="테이블을 선택하세요" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{tables.map((table) => (
|
|
<SelectItem key={table.tableName} value={table.tableName}>
|
|
{table.displayName || table.tableName}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
{/* 컬럼 설정 */}
|
|
<div className="space-y-2">
|
|
<Label>표시할 컬럼</Label>
|
|
<div className="space-y-2">
|
|
{/* 선택된 컬럼 목록 */}
|
|
{config.columns.length > 0 && (
|
|
<div className="border-border space-y-1 rounded border p-2">
|
|
{config.columns.map((col, index) => (
|
|
<div
|
|
key={col}
|
|
className="bg-muted flex items-center justify-between rounded px-2 py-1"
|
|
>
|
|
<span className="text-sm">{col}</span>
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => handleRemoveColumn(col)}
|
|
className="h-6 w-6 p-0"
|
|
>
|
|
<X className="h-3 w-3" />
|
|
</Button>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
{/* 컬럼 추가 */}
|
|
{availableColumns.length > 0 && (
|
|
<Select onValueChange={handleAddColumn}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="컬럼 추가" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{availableColumns
|
|
.filter((col) => !config.columns.includes(col.columnName))
|
|
.map((col) => (
|
|
<SelectItem key={col.columnName} value={col.columnName}>
|
|
{col.displayName || col.columnName}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* 체크박스 설정 */}
|
|
<div className="space-y-3">
|
|
<Label>체크박스 옵션</Label>
|
|
<div className="space-y-2">
|
|
<label className="flex items-center gap-2">
|
|
<Checkbox
|
|
checked={config.checkbox?.enabled !== false}
|
|
onCheckedChange={(checked) =>
|
|
handleChange({
|
|
...config,
|
|
checkbox: {
|
|
...config.checkbox,
|
|
enabled: checked as boolean,
|
|
},
|
|
})
|
|
}
|
|
/>
|
|
<span className="text-sm">체크박스 표시</span>
|
|
</label>
|
|
|
|
<label className="flex items-center gap-2">
|
|
<Checkbox
|
|
checked={config.checkbox?.selectAll !== false}
|
|
onCheckedChange={(checked) =>
|
|
handleChange({
|
|
...config,
|
|
checkbox: {
|
|
...config.checkbox,
|
|
selectAll: checked as boolean,
|
|
},
|
|
})
|
|
}
|
|
/>
|
|
<span className="text-sm">전체 선택 표시</span>
|
|
</label>
|
|
|
|
<label className="flex items-center gap-2">
|
|
<Checkbox
|
|
checked={config.checkbox?.multiple !== false}
|
|
onCheckedChange={(checked) =>
|
|
handleChange({
|
|
...config,
|
|
checkbox: {
|
|
...config.checkbox,
|
|
multiple: checked as boolean,
|
|
},
|
|
})
|
|
}
|
|
/>
|
|
<span className="text-sm">다중 선택 허용</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 헤더 설정 */}
|
|
<div className="space-y-3">
|
|
<Label>헤더 설정</Label>
|
|
<label className="flex items-center gap-2">
|
|
<Checkbox
|
|
checked={config.showCompanyName === true}
|
|
onCheckedChange={(checked) =>
|
|
handleChange({
|
|
...config,
|
|
showCompanyName: checked as boolean,
|
|
})
|
|
}
|
|
/>
|
|
<span className="text-sm font-medium">회사명 표시</span>
|
|
</label>
|
|
|
|
{config.showCompanyName && availableColumns.length > 0 && (
|
|
<div className="space-y-2 pl-6">
|
|
<Label className="text-xs">회사명 컬럼</Label>
|
|
<Select
|
|
value={config.companyNameColumn || ""}
|
|
onValueChange={(value) =>
|
|
handleChange({
|
|
...config,
|
|
companyNameColumn: value,
|
|
})
|
|
}
|
|
>
|
|
<SelectTrigger className="h-8 text-xs">
|
|
<SelectValue placeholder="컬럼 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{availableColumns.map((col) => (
|
|
<SelectItem key={col.columnName} value={col.columnName} className="text-xs">
|
|
{col.displayName || col.columnName}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
<p className="text-muted-foreground text-[10px]">
|
|
헤더에 표시할 회사명 데이터가 있는 컬럼을 선택하세요
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* 검색 영역 설정 */}
|
|
<div className="space-y-3">
|
|
<Label>검색/필터 영역</Label>
|
|
|
|
<label className="flex items-center gap-2">
|
|
<Checkbox
|
|
checked={config.showSearchArea === true}
|
|
onCheckedChange={(checked) =>
|
|
handleChange({
|
|
...config,
|
|
showSearchArea: checked as boolean,
|
|
})
|
|
}
|
|
/>
|
|
<span className="text-sm font-medium">
|
|
검색/필터 영역 표시
|
|
</span>
|
|
</label>
|
|
|
|
{config.showSearchArea && (
|
|
<div className="space-y-3 pl-6">
|
|
<div className="space-y-2">
|
|
<Label className="text-xs">검색 플레이스홀더</Label>
|
|
<Input
|
|
value={config.searchPlaceholder || ""}
|
|
onChange={(e) =>
|
|
handleChange({
|
|
...config,
|
|
searchPlaceholder: e.target.value,
|
|
})
|
|
}
|
|
placeholder="품목코드, 품목명, 규격 검색"
|
|
className="h-8 text-xs"
|
|
/>
|
|
</div>
|
|
|
|
{/* 카테고리 필터 설정 */}
|
|
<div className="space-y-2">
|
|
<label className="flex items-center gap-2">
|
|
<Checkbox
|
|
checked={config.enableCategoryFilter === true}
|
|
onCheckedChange={(checked) =>
|
|
handleChange({
|
|
...config,
|
|
enableCategoryFilter: checked as boolean,
|
|
})
|
|
}
|
|
/>
|
|
<span className="text-xs font-medium">카테고리 필터 표시</span>
|
|
</label>
|
|
|
|
{config.enableCategoryFilter && (
|
|
<div className="space-y-2 pl-6">
|
|
<Label className="text-xs">카테고리 목록 (쉼표로 구분)</Label>
|
|
<Input
|
|
value={(config.categories || []).join(", ")}
|
|
onChange={(e) =>
|
|
handleChange({
|
|
...config,
|
|
categories: e.target.value.split(",").map((c) => c.trim()).filter(Boolean),
|
|
})
|
|
}
|
|
placeholder="전체, 원자재, 반도체, 완제품"
|
|
className="h-8 text-xs"
|
|
/>
|
|
<p className="text-muted-foreground text-[10px]">
|
|
예: 전체, 원자재, 반도체, 완제품
|
|
</p>
|
|
|
|
{availableColumns.length > 0 && (
|
|
<>
|
|
<Label className="text-xs">카테고리 데이터 컬럼</Label>
|
|
<Select
|
|
value={config.categoryColumn || ""}
|
|
onValueChange={(value) =>
|
|
handleChange({
|
|
...config,
|
|
categoryColumn: value,
|
|
})
|
|
}
|
|
>
|
|
<SelectTrigger className="h-8 text-xs">
|
|
<SelectValue placeholder="컬럼 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{availableColumns.map((col) => (
|
|
<SelectItem key={col.columnName} value={col.columnName} className="text-xs">
|
|
{col.displayName || col.columnName}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* 빈 데이터 메시지 */}
|
|
<div className="space-y-2">
|
|
<Label>빈 데이터 메시지</Label>
|
|
<Input
|
|
value={config.emptyMessage || ""}
|
|
onChange={(e) =>
|
|
handleChange({ ...config, emptyMessage: e.target.value })
|
|
}
|
|
placeholder="데이터가 없습니다"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>빈 데이터 설명</Label>
|
|
<Input
|
|
value={config.emptyDescription || ""}
|
|
onChange={(e) =>
|
|
handleChange({ ...config, emptyDescription: e.target.value })
|
|
}
|
|
placeholder="품목 데이터가 추가되면 여기에 표시됩니다"
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|