247 lines
8.1 KiB
TypeScript
247 lines
8.1 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* UnifiedList 설정 패널
|
|
* 통합 목록 컴포넌트의 세부 설정을 관리합니다.
|
|
*/
|
|
|
|
import React from "react";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
import { Separator } from "@/components/ui/separator";
|
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Plus, Trash2 } from "lucide-react";
|
|
|
|
interface UnifiedListConfigPanelProps {
|
|
config: Record<string, any>;
|
|
onChange: (config: Record<string, any>) => void;
|
|
}
|
|
|
|
export const UnifiedListConfigPanel: React.FC<UnifiedListConfigPanelProps> = ({
|
|
config,
|
|
onChange,
|
|
}) => {
|
|
// 설정 업데이트 핸들러
|
|
const updateConfig = (field: string, value: any) => {
|
|
onChange({ ...config, [field]: value });
|
|
};
|
|
|
|
// 컬럼 관리
|
|
const columns = config.columns || [];
|
|
|
|
const addColumn = () => {
|
|
const newColumns = [...columns, { key: "", title: "", width: "" }];
|
|
updateConfig("columns", newColumns);
|
|
};
|
|
|
|
const updateColumn = (index: number, field: string, value: string) => {
|
|
const newColumns = [...columns];
|
|
newColumns[index] = { ...newColumns[index], [field]: value };
|
|
updateConfig("columns", newColumns);
|
|
};
|
|
|
|
const removeColumn = (index: number) => {
|
|
const newColumns = columns.filter((_: any, i: number) => i !== index);
|
|
updateConfig("columns", newColumns);
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
{/* 뷰 모드 */}
|
|
<div className="space-y-2">
|
|
<Label className="text-xs font-medium">표시 방식</Label>
|
|
<Select
|
|
value={config.viewMode || "table"}
|
|
onValueChange={(value) => updateConfig("viewMode", value)}
|
|
>
|
|
<SelectTrigger className="h-8 text-xs">
|
|
<SelectValue placeholder="방식 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="table">테이블</SelectItem>
|
|
<SelectItem value="card">카드</SelectItem>
|
|
<SelectItem value="kanban">칸반</SelectItem>
|
|
<SelectItem value="list">리스트</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
{/* 데이터 소스 */}
|
|
<div className="space-y-2">
|
|
<Label className="text-xs font-medium">데이터 소스</Label>
|
|
<Select
|
|
value={config.source || "static"}
|
|
onValueChange={(value) => updateConfig("source", value)}
|
|
>
|
|
<SelectTrigger className="h-8 text-xs">
|
|
<SelectValue placeholder="소스 선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="static">정적 데이터</SelectItem>
|
|
<SelectItem value="db">데이터베이스</SelectItem>
|
|
<SelectItem value="api">API</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
{/* DB 설정 */}
|
|
{config.source === "db" && (
|
|
<div className="space-y-2">
|
|
<Label className="text-xs font-medium">테이블명</Label>
|
|
<Input
|
|
value={config.tableName || ""}
|
|
onChange={(e) => updateConfig("tableName", e.target.value)}
|
|
placeholder="테이블명"
|
|
className="h-8 text-xs"
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{/* API 설정 */}
|
|
{config.source === "api" && (
|
|
<div className="space-y-2">
|
|
<Label className="text-xs font-medium">API 엔드포인트</Label>
|
|
<Input
|
|
value={config.apiEndpoint || ""}
|
|
onChange={(e) => updateConfig("apiEndpoint", e.target.value)}
|
|
placeholder="/api/list"
|
|
className="h-8 text-xs"
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
<Separator />
|
|
|
|
{/* 컬럼 설정 */}
|
|
<div className="space-y-2">
|
|
<div className="flex items-center justify-between">
|
|
<Label className="text-xs font-medium">컬럼 설정</Label>
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={addColumn}
|
|
className="h-6 px-2 text-xs"
|
|
>
|
|
<Plus className="h-3 w-3 mr-1" />
|
|
추가
|
|
</Button>
|
|
</div>
|
|
<div className="space-y-2 max-h-40 overflow-y-auto">
|
|
{columns.map((column: any, index: number) => (
|
|
<div key={index} className="flex items-center gap-2">
|
|
<Input
|
|
value={column.key || ""}
|
|
onChange={(e) => updateColumn(index, "key", e.target.value)}
|
|
placeholder="키"
|
|
className="h-7 text-xs flex-1"
|
|
/>
|
|
<Input
|
|
value={column.title || ""}
|
|
onChange={(e) => updateColumn(index, "title", e.target.value)}
|
|
placeholder="제목"
|
|
className="h-7 text-xs flex-1"
|
|
/>
|
|
<Input
|
|
value={column.width || ""}
|
|
onChange={(e) => updateColumn(index, "width", e.target.value)}
|
|
placeholder="너비"
|
|
className="h-7 text-xs w-16"
|
|
/>
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => removeColumn(index)}
|
|
className="h-7 w-7 p-0 text-destructive"
|
|
>
|
|
<Trash2 className="h-3 w-3" />
|
|
</Button>
|
|
</div>
|
|
))}
|
|
{columns.length === 0 && (
|
|
<p className="text-xs text-muted-foreground text-center py-2">
|
|
컬럼을 추가해주세요
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
{/* 기능 옵션 */}
|
|
<div className="space-y-3">
|
|
<Label className="text-xs font-medium">기능 옵션</Label>
|
|
|
|
<div className="flex items-center space-x-2">
|
|
<Checkbox
|
|
id="sortable"
|
|
checked={config.sortable !== false}
|
|
onCheckedChange={(checked) => updateConfig("sortable", checked)}
|
|
/>
|
|
<label htmlFor="sortable" className="text-xs">정렬 기능</label>
|
|
</div>
|
|
|
|
<div className="flex items-center space-x-2">
|
|
<Checkbox
|
|
id="pagination"
|
|
checked={config.pagination !== false}
|
|
onCheckedChange={(checked) => updateConfig("pagination", checked)}
|
|
/>
|
|
<label htmlFor="pagination" className="text-xs">페이지네이션</label>
|
|
</div>
|
|
|
|
<div className="flex items-center space-x-2">
|
|
<Checkbox
|
|
id="searchable"
|
|
checked={config.searchable || false}
|
|
onCheckedChange={(checked) => updateConfig("searchable", checked)}
|
|
/>
|
|
<label htmlFor="searchable" className="text-xs">검색 기능</label>
|
|
</div>
|
|
|
|
<div className="flex items-center space-x-2">
|
|
<Checkbox
|
|
id="editable"
|
|
checked={config.editable || false}
|
|
onCheckedChange={(checked) => updateConfig("editable", checked)}
|
|
/>
|
|
<label htmlFor="editable" className="text-xs">인라인 편집</label>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 페이지 크기 */}
|
|
{config.pagination !== false && (
|
|
<div className="space-y-2">
|
|
<Label className="text-xs font-medium">페이지당 행 수</Label>
|
|
<Select
|
|
value={String(config.pageSize || 10)}
|
|
onValueChange={(value) => updateConfig("pageSize", Number(value))}
|
|
>
|
|
<SelectTrigger className="h-8 text-xs">
|
|
<SelectValue placeholder="선택" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="5">5개</SelectItem>
|
|
<SelectItem value="10">10개</SelectItem>
|
|
<SelectItem value="20">20개</SelectItem>
|
|
<SelectItem value="50">50개</SelectItem>
|
|
<SelectItem value="100">100개</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
UnifiedListConfigPanel.displayName = "UnifiedListConfigPanel";
|
|
|
|
export default UnifiedListConfigPanel;
|
|
|
|
|