"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 { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Check, ChevronsUpDown, Loader2 } from "lucide-react"; import { cn } from "@/lib/utils"; import { tableTypeApi } from "@/lib/api/screen"; import { TimelineSchedulerConfig } from "./types"; import { zoomLevelOptions, statusOptions } from "./config"; interface TimelineSchedulerConfigPanelProps { config: TimelineSchedulerConfig; onChange: (config: Partial) => void; } interface TableInfo { tableName: string; displayName: string; } interface ColumnInfo { columnName: string; displayName: string; } export function TimelineSchedulerConfigPanel({ config, onChange, }: TimelineSchedulerConfigPanelProps) { // πŸ› 디버깅: 받은 config 좜λ ₯ console.log("πŸ› [TimelineSchedulerConfigPanel] config:", { selectedTable: config.selectedTable, fieldMapping: config.fieldMapping, fieldMappingKeys: config.fieldMapping ? Object.keys(config.fieldMapping) : [], }); const [tables, setTables] = useState([]); const [tableColumns, setTableColumns] = useState([]); const [resourceColumns, setResourceColumns] = useState([]); const [loading, setLoading] = useState(false); const [tableSelectOpen, setTableSelectOpen] = useState(false); const [resourceTableSelectOpen, setResourceTableSelectOpen] = useState(false); // ν…Œμ΄λΈ” λͺ©λ‘ λ‘œλ“œ useEffect(() => { const loadTables = async () => { setLoading(true); try { const tableList = await tableTypeApi.getTables(); if (Array.isArray(tableList)) { setTables( tableList.map((t: any) => ({ tableName: t.table_name || t.tableName, displayName: t.display_name || t.displayName || t.table_name || t.tableName, })) ); } } catch (err) { console.error("ν…Œμ΄λΈ” λͺ©λ‘ λ‘œλ“œ 였λ₯˜:", err); } finally { setLoading(false); } }; loadTables(); }, []); // μŠ€μΌ€μ€„ ν…Œμ΄λΈ” 컬럼 λ‘œλ“œ useEffect(() => { const loadColumns = async () => { if (!config.selectedTable) { setTableColumns([]); return; } try { const columns = await tableTypeApi.getColumns(config.selectedTable); if (Array.isArray(columns)) { setTableColumns( columns.map((col: any) => ({ columnName: col.column_name || col.columnName, displayName: col.display_name || col.displayName || col.column_name || col.columnName, })) ); } } catch (err) { console.error("컬럼 λ‘œλ“œ 였λ₯˜:", err); setTableColumns([]); } }; loadColumns(); }, [config.selectedTable]); // λ¦¬μ†ŒμŠ€ ν…Œμ΄λΈ” 컬럼 λ‘œλ“œ useEffect(() => { const loadResourceColumns = async () => { if (!config.resourceTable) { setResourceColumns([]); return; } try { const columns = await tableTypeApi.getColumns(config.resourceTable); if (Array.isArray(columns)) { setResourceColumns( columns.map((col: any) => ({ columnName: col.column_name || col.columnName, displayName: col.display_name || col.displayName || col.column_name || col.columnName, })) ); } } catch (err) { console.error("λ¦¬μ†ŒμŠ€ 컬럼 λ‘œλ“œ 였λ₯˜:", err); setResourceColumns([]); } }; loadResourceColumns(); }, [config.resourceTable]); // μ„€μ • μ—…λ°μ΄νŠΈ 헬퍼 const updateConfig = (updates: Partial) => { onChange({ ...config, ...updates }); }; // πŸ†• 이전 ν˜•μ‹(idField)κ³Ό μƒˆ ν˜•μ‹(id) λͺ¨λ‘ μ§€μ›ν•˜λŠ” 헬퍼 ν•¨μˆ˜ const getFieldMappingValue = (newKey: string, oldKey: string): string => { const mapping = config.fieldMapping as Record | undefined; if (!mapping) return ""; return mapping[newKey] || mapping[oldKey] || ""; }; // ν•„λ“œ λ§€ν•‘ μ—…λ°μ΄νŠΈ (μƒˆ ν˜•μ‹μœΌλ‘œ μ €μž₯ν•˜κ³ , 이전 ν˜•μ‹ ν‚€ μ‚­μ œ) const updateFieldMapping = (field: string, value: string) => { const currentMapping = { ...config.fieldMapping } as Record; // 이전 ν˜•μ‹ ν‚€ λ§€ν•‘ const oldKeyMap: Record = { id: "idField", resourceId: "resourceIdField", title: "titleField", startDate: "startDateField", endDate: "endDateField", status: "statusField", progress: "progressField", color: "colorField", }; // μƒˆ ν˜•μ‹μœΌλ‘œ μ €μž₯ currentMapping[field] = value; // 이전 ν˜•μ‹ ν‚€κ°€ 있으면 μ‚­μ œ const oldKey = oldKeyMap[field]; if (oldKey && currentMapping[oldKey]) { delete currentMapping[oldKey]; } updateConfig({ fieldMapping: currentMapping, }); }; // λ¦¬μ†ŒμŠ€ ν•„λ“œ λ§€ν•‘ μ—…λ°μ΄νŠΈ const updateResourceFieldMapping = (field: string, value: string) => { updateConfig({ resourceFieldMapping: { ...config.resourceFieldMapping, id: config.resourceFieldMapping?.id || "id", name: config.resourceFieldMapping?.name || "name", [field]: value, }, }); }; return (
{/* ν…Œμ΄λΈ” μ„€μ • */} ν…Œμ΄λΈ” μ„€μ • {/* μŠ€μΌ€μ€„ ν…Œμ΄λΈ” 선택 */}
{ const lowerSearch = search.toLowerCase(); if (value.toLowerCase().includes(lowerSearch)) { return 1; } return 0; }} > ν…Œμ΄λΈ”μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€. {tables.map((table) => ( { updateConfig({ selectedTable: table.tableName }); setTableSelectOpen(false); }} className="text-xs" >
{table.displayName} {table.tableName}
))}
{/* λ¦¬μ†ŒμŠ€ ν…Œμ΄λΈ” 선택 */}
{ const lowerSearch = search.toLowerCase(); if (value.toLowerCase().includes(lowerSearch)) { return 1; } return 0; }} > ν…Œμ΄λΈ”μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€. {tables.map((table) => ( { updateConfig({ resourceTable: table.tableName }); setResourceTableSelectOpen(false); }} className="text-xs" >
{table.displayName} {table.tableName}
))}
{/* ν•„λ“œ λ§€ν•‘ */} ν•„λ“œ λ§€ν•‘ {/* μŠ€μΌ€μ€„ ν•„λ“œ λ§€ν•‘ */} {config.selectedTable && (
{/* ID ν•„λ“œ */}
{/* λ¦¬μ†ŒμŠ€ ID ν•„λ“œ */}
{/* 제λͺ© ν•„λ“œ */}
{/* μ‹œμž‘μΌ ν•„λ“œ */}
{/* μ’…λ£ŒμΌ ν•„λ“œ */}
{/* μƒνƒœ ν•„λ“œ */}
)} {/* λ¦¬μ†ŒμŠ€ ν•„λ“œ λ§€ν•‘ */} {config.resourceTable && (
{/* ID ν•„λ“œ */}
{/* 이름 ν•„λ“œ */}
)}
{/* ν‘œμ‹œ μ„€μ • */} ν‘œμ‹œ μ„€μ • {/* κΈ°λ³Έ 쀌 레벨 */}
{/* 높이 */}
updateConfig({ height: parseInt(e.target.value) || 500 }) } className="h-8 text-xs" />
{/* ν–‰ 높이 */}
updateConfig({ rowHeight: parseInt(e.target.value) || 50 }) } className="h-8 text-xs" />
{/* ν† κΈ€ μŠ€μœ„μΉ˜λ“€ */}
updateConfig({ editable: v })} />
updateConfig({ draggable: v })} />
updateConfig({ resizable: v })} />
updateConfig({ showTodayLine: v })} />
updateConfig({ showProgress: v })} />
updateConfig({ showToolbar: v })} />
); } export default TimelineSchedulerConfigPanel;