288 lines
9.3 KiB
TypeScript
288 lines
9.3 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Switch } from "@/components/ui/switch";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select";
|
|
import { RackStructureComponentConfig, FieldMapping } from "./types";
|
|
|
|
interface RackStructureConfigPanelProps {
|
|
config: RackStructureComponentConfig;
|
|
onChange: (config: RackStructureComponentConfig) => void;
|
|
// 화면관리에서 전달하는 테이블 컬럼 정보
|
|
tables?: Array<{
|
|
tableName: string;
|
|
tableLabel?: string;
|
|
columns: Array<{
|
|
columnName: string;
|
|
columnLabel?: string;
|
|
dataType?: string;
|
|
}>;
|
|
}>;
|
|
}
|
|
|
|
export const RackStructureConfigPanel: React.FC<RackStructureConfigPanelProps> = ({
|
|
config,
|
|
onChange,
|
|
tables = [],
|
|
}) => {
|
|
// 사용 가능한 컬럼 목록 추출
|
|
const [availableColumns, setAvailableColumns] = useState<
|
|
Array<{ value: string; label: string }>
|
|
>([]);
|
|
|
|
useEffect(() => {
|
|
// 모든 테이블의 컬럼을 플랫하게 추출
|
|
const columns: Array<{ value: string; label: string }> = [];
|
|
tables.forEach((table) => {
|
|
table.columns.forEach((col) => {
|
|
columns.push({
|
|
value: col.columnName,
|
|
label: col.columnLabel || col.columnName,
|
|
});
|
|
});
|
|
});
|
|
setAvailableColumns(columns);
|
|
}, [tables]);
|
|
|
|
const handleChange = (key: keyof RackStructureComponentConfig, value: any) => {
|
|
onChange({ ...config, [key]: value });
|
|
};
|
|
|
|
const handleFieldMappingChange = (field: keyof FieldMapping, value: string) => {
|
|
const currentMapping = config.fieldMapping || {};
|
|
onChange({
|
|
...config,
|
|
fieldMapping: {
|
|
...currentMapping,
|
|
[field]: value === "__none__" ? undefined : value,
|
|
},
|
|
});
|
|
};
|
|
|
|
const fieldMapping = config.fieldMapping || {};
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
{/* 필드 매핑 섹션 */}
|
|
<div className="space-y-3">
|
|
<div className="text-sm font-medium text-gray-700">필드 매핑</div>
|
|
<p className="text-xs text-gray-500">
|
|
상위 폼에 배치된 필드 중 어떤 필드를 사용할지 선택하세요
|
|
</p>
|
|
|
|
{/* 창고 코드 필드 */}
|
|
<div>
|
|
<Label className="text-xs">창고 코드 필드</Label>
|
|
<Select
|
|
value={fieldMapping.warehouseCodeField || "__none__"}
|
|
onValueChange={(v) => handleFieldMappingChange("warehouseCodeField", v)}
|
|
>
|
|
<SelectTrigger className="h-8">
|
|
<SelectValue placeholder="필드 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="__none__">선택 안함</SelectItem>
|
|
{availableColumns.map((col) => (
|
|
<SelectItem key={col.value} value={col.value}>
|
|
{col.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
{/* 창고명 필드 */}
|
|
<div>
|
|
<Label className="text-xs">창고명 필드</Label>
|
|
<Select
|
|
value={fieldMapping.warehouseNameField || "__none__"}
|
|
onValueChange={(v) => handleFieldMappingChange("warehouseNameField", v)}
|
|
>
|
|
<SelectTrigger className="h-8">
|
|
<SelectValue placeholder="필드 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="__none__">선택 안함</SelectItem>
|
|
{availableColumns.map((col) => (
|
|
<SelectItem key={col.value} value={col.value}>
|
|
{col.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
{/* 층 필드 */}
|
|
<div>
|
|
<Label className="text-xs">층 필드</Label>
|
|
<Select
|
|
value={fieldMapping.floorField || "__none__"}
|
|
onValueChange={(v) => handleFieldMappingChange("floorField", v)}
|
|
>
|
|
<SelectTrigger className="h-8">
|
|
<SelectValue placeholder="필드 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="__none__">선택 안함</SelectItem>
|
|
{availableColumns.map((col) => (
|
|
<SelectItem key={col.value} value={col.value}>
|
|
{col.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
{/* 구역 필드 */}
|
|
<div>
|
|
<Label className="text-xs">구역 필드</Label>
|
|
<Select
|
|
value={fieldMapping.zoneField || "__none__"}
|
|
onValueChange={(v) => handleFieldMappingChange("zoneField", v)}
|
|
>
|
|
<SelectTrigger className="h-8">
|
|
<SelectValue placeholder="필드 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="__none__">선택 안함</SelectItem>
|
|
{availableColumns.map((col) => (
|
|
<SelectItem key={col.value} value={col.value}>
|
|
{col.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
{/* 위치 유형 필드 */}
|
|
<div>
|
|
<Label className="text-xs">위치 유형 필드</Label>
|
|
<Select
|
|
value={fieldMapping.locationTypeField || "__none__"}
|
|
onValueChange={(v) => handleFieldMappingChange("locationTypeField", v)}
|
|
>
|
|
<SelectTrigger className="h-8">
|
|
<SelectValue placeholder="필드 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="__none__">선택 안함</SelectItem>
|
|
{availableColumns.map((col) => (
|
|
<SelectItem key={col.value} value={col.value}>
|
|
{col.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
{/* 사용 여부 필드 */}
|
|
<div>
|
|
<Label className="text-xs">사용 여부 필드</Label>
|
|
<Select
|
|
value={fieldMapping.statusField || "__none__"}
|
|
onValueChange={(v) => handleFieldMappingChange("statusField", v)}
|
|
>
|
|
<SelectTrigger className="h-8">
|
|
<SelectValue placeholder="필드 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="__none__">선택 안함</SelectItem>
|
|
{availableColumns.map((col) => (
|
|
<SelectItem key={col.value} value={col.value}>
|
|
{col.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 제한 설정 */}
|
|
<div className="space-y-3 border-t pt-3">
|
|
<div className="text-sm font-medium text-gray-700">제한 설정</div>
|
|
|
|
<div>
|
|
<Label className="text-xs">최대 조건 수</Label>
|
|
<Input
|
|
type="number"
|
|
min={1}
|
|
max={20}
|
|
value={config.maxConditions || 10}
|
|
onChange={(e) => handleChange("maxConditions", parseInt(e.target.value) || 10)}
|
|
className="h-8"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label className="text-xs">최대 열 수</Label>
|
|
<Input
|
|
type="number"
|
|
min={1}
|
|
max={999}
|
|
value={config.maxRows || 99}
|
|
onChange={(e) => handleChange("maxRows", parseInt(e.target.value) || 99)}
|
|
className="h-8"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label className="text-xs">최대 단 수</Label>
|
|
<Input
|
|
type="number"
|
|
min={1}
|
|
max={99}
|
|
value={config.maxLevels || 20}
|
|
onChange={(e) => handleChange("maxLevels", parseInt(e.target.value) || 20)}
|
|
className="h-8"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* UI 설정 */}
|
|
<div className="space-y-3 border-t pt-3">
|
|
<div className="text-sm font-medium text-gray-700">UI 설정</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<Label className="text-xs">템플릿 기능</Label>
|
|
<Switch
|
|
checked={config.showTemplates ?? true}
|
|
onCheckedChange={(checked) => handleChange("showTemplates", checked)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<Label className="text-xs">미리보기 표시</Label>
|
|
<Switch
|
|
checked={config.showPreview ?? true}
|
|
onCheckedChange={(checked) => handleChange("showPreview", checked)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<Label className="text-xs">통계 카드 표시</Label>
|
|
<Switch
|
|
checked={config.showStatistics ?? true}
|
|
onCheckedChange={(checked) => handleChange("showStatistics", checked)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex items-center justify-between">
|
|
<Label className="text-xs">읽기 전용</Label>
|
|
<Switch
|
|
checked={config.readonly ?? false}
|
|
onCheckedChange={(checked) => handleChange("readonly", checked)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|