"use client"; import React, { useState, useEffect } from "react"; import { useSortable } from "@dnd-kit/sortable"; import { CSS } from "@dnd-kit/utilities"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Checkbox } from "@/components/ui/checkbox"; import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Check, ChevronsUpDown, GripVertical, Link2, X } from "lucide-react"; import { cn } from "@/lib/utils"; export function SortableColumnRow({ id, col, index, isNumeric, isEntityJoin, onLabelChange, onWidthChange, onFormatChange, onRemove, onShowInSummaryChange, onShowInDetailChange, }: { id: string; col: { name: string; label: string; width?: number; format?: any; showInSummary?: boolean; showInDetail?: boolean }; index: number; isNumeric: boolean; isEntityJoin?: boolean; onLabelChange: (value: string) => void; onWidthChange: (value: number) => void; onFormatChange: (checked: boolean) => void; onRemove: () => void; onShowInSummaryChange?: (checked: boolean) => void; onShowInDetailChange?: (checked: boolean) => void; }) { const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id }); const style = { transform: CSS.Transform.toString(transform), transition }; return (
{isEntityJoin ? ( ) : ( #{index + 1} )} onLabelChange(e.target.value)} placeholder="라벨" className="h-6 min-w-0 flex-1 text-xs" /> onWidthChange(parseInt(e.target.value) || 100)} placeholder="너비" className="h-6 w-14 shrink-0 text-xs" /> {isNumeric && ( )} {onShowInSummaryChange && ( )} {onShowInDetailChange && ( )}
); } export const GroupByColumnsSelector: React.FC<{ tableName?: string; selectedColumns: string[]; onChange: (columns: string[]) => void; }> = ({ tableName, selectedColumns, onChange }) => { const [columns, setColumns] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { if (!tableName) { setColumns([]); return; } const loadColumns = async () => { setLoading(true); try { const { tableManagementApi } = await import("@/lib/api/tableManagement"); const response = await tableManagementApi.getColumnList(tableName); if (response.success && response.data && response.data.columns) { setColumns(response.data.columns); } } catch (error) { console.error("컬럼 정보 로드 실패:", error); } finally { setLoading(false); } }; loadColumns(); }, [tableName]); const toggleColumn = (columnName: string) => { const newSelection = selectedColumns.includes(columnName) ? selectedColumns.filter((c) => c !== columnName) : [...selectedColumns, columnName]; onChange(newSelection); }; if (!tableName) { return (

먼저 우측 패널의 테이블을 선택하세요

); } return (
{loading ? (

로딩 중...

) : columns.length === 0 ? (

컬럼을 찾을 수 없습니다

) : (
{columns.map((col) => (
toggleColumn(col.columnName)} />
))}
)}

선택된 컬럼: {selectedColumns.length > 0 ? selectedColumns.join(", ") : "없음"}
같은 값을 가진 모든 레코드를 함께 불러옵니다

); }; export const ScreenSelector: React.FC<{ value?: number; onChange: (screenId?: number) => void; }> = ({ value, onChange }) => { const [open, setOpen] = useState(false); const [screens, setScreens] = useState>([]); const [loading, setLoading] = useState(false); useEffect(() => { const loadScreens = async () => { setLoading(true); try { const { screenApi } = await import("@/lib/api/screen"); const response = await screenApi.getScreens({ page: 1, size: 1000 }); setScreens( response.data.map((s) => ({ screenId: s.screenId, screenName: s.screenName, screenCode: s.screenCode })), ); } catch (error) { console.error("화면 목록 로드 실패:", error); } finally { setLoading(false); } }; loadScreens(); }, []); const selectedScreen = screens.find((s) => s.screenId === value); return ( 화면을 찾을 수 없습니다. {screens.map((screen) => ( { onChange(screen.screenId === value ? undefined : screen.screenId); setOpen(false); }} className="text-xs" >
{screen.screenName} {screen.screenCode}
))}
); };