"use client"; import React, { useState, useMemo, useEffect } from "react"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Card, CardContent } from "@/components/ui/card"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { Plus, X, ChevronDown, ChevronRight } from "lucide-react"; import { SelectedItemsDetailInputConfig, AdditionalFieldDefinition, FieldGroup, DisplayItem, DisplayItemType, EmptyBehavior, DisplayFieldFormat } from "./types"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Check, ChevronsUpDown } from "lucide-react"; import { cn } from "@/lib/utils"; import { getSecondLevelMenus, getCategoryColumns, getCategoryValues } from "@/lib/api/tableCategoryValue"; import { CalculationBuilder } from "./CalculationBuilder"; export interface SelectedItemsDetailInputConfigPanelProps { config: SelectedItemsDetailInputConfig; onChange: (config: Partial) => void; sourceTableColumns?: Array<{ columnName: string; columnLabel?: string; dataType?: string }>; // πŸ†• 원본 ν…Œμ΄λΈ” 컬럼 targetTableColumns?: Array<{ columnName: string; columnLabel?: string; dataType?: string }>; // πŸ†• λŒ€μƒ ν…Œμ΄λΈ” 컬럼 allTables?: Array<{ tableName: string; displayName?: string }>; screenTableName?: string; // πŸ†• ν˜„μž¬ ν™”λ©΄μ˜ ν…Œμ΄λΈ”λͺ… (μžλ™ μ„€μ •μš©) onSourceTableChange?: (tableName: string) => void; // πŸ†• 원본 ν…Œμ΄λΈ” λ³€κ²½ 콜백 onTargetTableChange?: (tableName: string) => void; // πŸ†• λŒ€μƒ ν…Œμ΄λΈ” λ³€κ²½ 콜백 (κΈ°μ‘΄ onTableChange λŒ€μ²΄) } /** * SelectedItemsDetailInput μ„€μ • νŒ¨λ„ * μ»΄ν¬λ„ŒνŠΈμ˜ 섀정값듀을 νŽΈμ§‘ν•  수 μžˆλŠ” UI 제곡 */ export const SelectedItemsDetailInputConfigPanel: React.FC = ({ config, onChange, sourceTableColumns = [], // πŸ†• 원본 ν…Œμ΄λΈ” 컬럼 targetTableColumns = [], // πŸ†• λŒ€μƒ ν…Œμ΄λΈ” 컬럼 allTables = [], screenTableName, // πŸ†• ν˜„μž¬ ν™”λ©΄μ˜ ν…Œμ΄λΈ”λͺ… onSourceTableChange, // πŸ†• 원본 ν…Œμ΄λΈ” λ³€κ²½ 콜백 onTargetTableChange, // πŸ†• λŒ€μƒ ν…Œμ΄λΈ” λ³€κ²½ 콜백 }) => { const [localFields, setLocalFields] = useState(config.additionalFields || []); const [displayColumns, setDisplayColumns] = useState>(config.displayColumns || []); const [fieldPopoverOpen, setFieldPopoverOpen] = useState>({}); // πŸ†• ν•„λ“œ κ·Έλ£Ή μƒνƒœ const [localFieldGroups, setLocalFieldGroups] = useState(config.fieldGroups || []); // πŸ†• 그룹별 펼침/μ ‘νž˜ μƒνƒœ const [expandedGroups, setExpandedGroups] = useState>({}); // πŸ†• 그룹별 ν‘œμ‹œ ν•­λͺ© μ„€μ • 펼침/μ ‘νž˜ μƒνƒœ const [expandedDisplayItems, setExpandedDisplayItems] = useState>({}); // πŸ†• 원본 ν…Œμ΄λΈ” 선택 μƒνƒœ const [sourceTableSelectOpen, setSourceTableSelectOpen] = useState(false); const [sourceTableSearchValue, setSourceTableSearchValue] = useState(""); // πŸ†• λŒ€μƒ ν…Œμ΄λΈ” 선택 μƒνƒœ (κΈ°μ‘΄ tableSelectOpen) const [tableSelectOpen, setTableSelectOpen] = useState(false); const [tableSearchValue, setTableSearchValue] = useState(""); // πŸ†• μΉ΄ν…Œκ³ λ¦¬ 맀핑을 μœ„ν•œ μƒνƒœ const [secondLevelMenus, setSecondLevelMenus] = useState>([]); const [categoryColumns, setCategoryColumns] = useState>>({}); const [categoryValues, setCategoryValues] = useState>>({}); // 2레벨 메뉴 λͺ©λ‘ λ‘œλ“œ useEffect(() => { const loadMenus = async () => { const response = await getSecondLevelMenus(); if (response.success && response.data) { setSecondLevelMenus(response.data); } }; loadMenus(); }, []); // 메뉴 선택 μ‹œ μΉ΄ν…Œκ³ λ¦¬ λͺ©λ‘ λ‘œλ“œ const handleMenuSelect = async (menuObjid: number, fieldType: "discountType" | "roundingType" | "roundingUnit") => { if (!config.targetTable) { console.warn("⚠️ targetTable이 μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€"); return; } console.log("πŸ” μΉ΄ν…Œκ³ λ¦¬ λͺ©λ‘ λ‘œλ“œ μ‹œμž‘", { targetTable: config.targetTable, menuObjid, fieldType }); const response = await getCategoryColumns(config.targetTable); console.log("πŸ“₯ getCategoryColumns 응닡:", response); if (response.success && response.data) { console.log("βœ… μΉ΄ν…Œκ³ λ¦¬ 컬럼 데이터:", response.data); setCategoryColumns(prev => ({ ...prev, [fieldType]: response.data })); } else { console.error("❌ μΉ΄ν…Œκ³ λ¦¬ 컬럼 λ‘œλ“œ μ‹€νŒ¨:", response); } // valueMapping μ—…λ°μ΄νŠΈ handleChange("autoCalculation", { ...config.autoCalculation, valueMapping: { ...config.autoCalculation.valueMapping, _selectedMenus: { ...(config.autoCalculation.valueMapping as any)?._selectedMenus, [fieldType]: menuObjid, }, }, }); }; // μΉ΄ν…Œκ³ λ¦¬ 선택 μ‹œ μΉ΄ν…Œκ³ λ¦¬ κ°’ λͺ©λ‘ λ‘œλ“œ const handleCategorySelect = async (columnName: string, menuObjid: number, fieldType: "discountType" | "roundingType" | "roundingUnit") => { if (!config.targetTable) return; const response = await getCategoryValues(config.targetTable, columnName, false, menuObjid); if (response.success && response.data) { setCategoryValues(prev => ({ ...prev, [fieldType]: response.data })); } // valueMapping μ—…λ°μ΄νŠΈ handleChange("autoCalculation", { ...config.autoCalculation, valueMapping: { ...config.autoCalculation.valueMapping, _selectedCategories: { ...(config.autoCalculation.valueMapping as any)?._selectedCategories, [fieldType]: columnName, }, }, }); }; // πŸ†• 초기 λ‘œλ“œ μ‹œ screenTableName을 targetTable둜 μžλ™ μ„€μ • React.useEffect(() => { if (screenTableName && !config.targetTable) { console.log("✨ ν˜„μž¬ ν™”λ©΄ ν…Œμ΄λΈ”μ„ μ €μž₯ λŒ€μƒ ν…Œμ΄λΈ”λ‘œ μžλ™ μ„€μ •:", screenTableName); handleChange("targetTable", screenTableName); // μ»¬λŸΌλ„ μžλ™ λ‘œλ“œ if (onTargetTableChange) { onTargetTableChange(screenTableName); } } }, [screenTableName]); // config.targetTable은 μ˜μ‘΄μ„±μ—μ„œ μ œμ™Έ (ν•œ 번만 μ‹€ν–‰) const handleChange = (key: keyof SelectedItemsDetailInputConfig, value: any) => { onChange({ [key]: value }); }; const handleFieldsChange = (fields: AdditionalFieldDefinition[]) => { setLocalFields(fields); handleChange("additionalFields", fields); }; const handleDisplayColumnsChange = (columns: Array<{ name: string; label: string; width?: string }>) => { setDisplayColumns(columns); handleChange("displayColumns", columns); }; // ν•„λ“œ μΆ”κ°€ const addField = () => { const newField: AdditionalFieldDefinition = { name: `field_${localFields.length + 1}`, label: `ν•„λ“œ ${localFields.length + 1}`, type: "text", }; handleFieldsChange([...localFields, newField]); }; // ν•„λ“œ 제거 const removeField = (index: number) => { handleFieldsChange(localFields.filter((_, i) => i !== index)); }; // ν•„λ“œ μˆ˜μ • const updateField = (index: number, updates: Partial) => { const newFields = [...localFields]; newFields[index] = { ...newFields[index], ...updates }; handleFieldsChange(newFields); }; // πŸ†• ν•„λ“œ κ·Έλ£Ή 관리 const handleFieldGroupsChange = (groups: FieldGroup[]) => { setLocalFieldGroups(groups); handleChange("fieldGroups", groups); }; const addFieldGroup = () => { const newGroup: FieldGroup = { id: `group_${localFieldGroups.length + 1}`, title: `κ·Έλ£Ή ${localFieldGroups.length + 1}`, order: localFieldGroups.length, }; handleFieldGroupsChange([...localFieldGroups, newGroup]); }; const removeFieldGroup = (groupId: string) => { // κ·Έλ£Ή μ‚­μ œ μ‹œ ν•΄λ‹Ή 그룹에 μ†ν•œ ν•„λ“œλ“€μ˜ groupId도 제거 const updatedFields = localFields.map(field => field.groupId === groupId ? { ...field, groupId: undefined } : field ); setLocalFields(updatedFields); handleChange("additionalFields", updatedFields); handleFieldGroupsChange(localFieldGroups.filter(g => g.id !== groupId)); }; const updateFieldGroup = (groupId: string, updates: Partial) => { const newGroups = localFieldGroups.map(g => g.id === groupId ? { ...g, ...updates } : g ); handleFieldGroupsChange(newGroups); }; // ν‘œμ‹œ 컬럼 μΆ”κ°€ const addDisplayColumn = (columnName: string, columnLabel: string) => { if (!displayColumns.some(col => col.name === columnName)) { handleDisplayColumnsChange([...displayColumns, { name: columnName, label: columnLabel }]); } }; // ν‘œμ‹œ 컬럼 제거 const removeDisplayColumn = (columnName: string) => { handleDisplayColumnsChange(displayColumns.filter((col) => col.name !== columnName)); }; // πŸ†• ν‘œμ‹œ 컬럼용: 원본 ν…Œμ΄λΈ”μ—μ„œ μ‚¬μš©λ˜μ§€ μ•Šμ€ 컬럼 λͺ©λ‘ const availableColumns = useMemo(() => { const usedColumns = new Set([...displayColumns.map(c => c.name), ...localFields.map((f) => f.name)]); return sourceTableColumns.filter((col) => !usedColumns.has(col.columnName)); }, [sourceTableColumns, displayColumns, localFields]); // πŸ†• μΆ”κ°€ μž…λ ₯ ν•„λ“œμš©: λŒ€μƒ ν…Œμ΄λΈ”μ—μ„œ μ‚¬μš©λ˜μ§€ μ•Šμ€ 컬럼 λͺ©λ‘ const availableTargetColumns = useMemo(() => { const usedColumns = new Set([...displayColumns.map(c => c.name), ...localFields.map((f) => f.name)]); return targetTableColumns.filter((col) => !usedColumns.has(col.columnName)); }, [targetTableColumns, displayColumns, localFields]); // πŸ†• 원본 ν…Œμ΄λΈ” 필터링 const filteredSourceTables = useMemo(() => { if (!sourceTableSearchValue) return allTables; const searchLower = sourceTableSearchValue.toLowerCase(); return allTables.filter( (table) => table.tableName.toLowerCase().includes(searchLower) || table.displayName?.toLowerCase().includes(searchLower), ); }, [allTables, sourceTableSearchValue]); // πŸ†• 그룹별 ν•­λͺ© ν‘œμ‹œ μ„€μ • ν•Έλ“€λŸ¬ const addDisplayItemToGroup = (groupId: string, type: DisplayItemType) => { const newItem: DisplayItem = { type, id: `display-${Date.now()}`, }; if (type === "field") { // ν•΄λ‹Ή 그룹의 ν•„λ“œλ§Œ 선택 κ°€λŠ₯ν•˜λ„λ‘ const groupFields = localFields.filter(f => f.groupId === groupId); newItem.fieldName = groupFields[0]?.name || ""; newItem.format = "text"; newItem.emptyBehavior = "default"; } else if (type === "icon") { newItem.icon = "Circle"; } else if (type === "text") { newItem.value = "ν…μŠ€νŠΈ"; } const updatedGroups = localFieldGroups.map(g => { if (g.id === groupId) { return { ...g, displayItems: [...(g.displayItems || []), newItem] }; } return g; }); setLocalFieldGroups(updatedGroups); handleChange("fieldGroups", updatedGroups); }; const removeDisplayItemFromGroup = (groupId: string, itemIndex: number) => { const updatedGroups = localFieldGroups.map(g => { if (g.id === groupId) { return { ...g, displayItems: (g.displayItems || []).filter((_, i) => i !== itemIndex) }; } return g; }); setLocalFieldGroups(updatedGroups); handleChange("fieldGroups", updatedGroups); }; const updateDisplayItemInGroup = (groupId: string, itemIndex: number, updates: Partial) => { const updatedGroups = localFieldGroups.map(g => { if (g.id === groupId) { const updatedItems = [...(g.displayItems || [])]; updatedItems[itemIndex] = { ...updatedItems[itemIndex], ...updates }; return { ...g, displayItems: updatedItems }; } return g; }); setLocalFieldGroups(updatedGroups); handleChange("fieldGroups", updatedGroups); }; // πŸ†• μ„ νƒλœ 원본 ν…Œμ΄λΈ” ν‘œμ‹œλͺ… const selectedSourceTableLabel = useMemo(() => { if (!config.sourceTable) return "원본 ν…Œμ΄λΈ”μ„ μ„ νƒν•˜μ„Έμš”"; const table = allTables.find((t) => t.tableName === config.sourceTable); return table ? table.displayName || table.tableName : config.sourceTable; }, [config.sourceTable, allTables]); // λŒ€μƒ ν…Œμ΄λΈ” 필터링 const filteredTables = useMemo(() => { if (!tableSearchValue) return allTables; const searchLower = tableSearchValue.toLowerCase(); return allTables.filter( (table) => table.tableName.toLowerCase().includes(searchLower) || table.displayName?.toLowerCase().includes(searchLower), ); }, [allTables, tableSearchValue]); // μ„ νƒλœ λŒ€μƒ ν…Œμ΄λΈ” ν‘œμ‹œλͺ… const selectedTableLabel = useMemo(() => { if (!config.targetTable) return "μ €μž₯ λŒ€μƒ ν…Œμ΄λΈ”μ„ μ„ νƒν•˜μ„Έμš”"; const table = allTables.find((t) => t.tableName === config.targetTable); return table ? table.displayName || table.tableName : config.targetTable; }, [config.targetTable, allTables]); return (
{/* 데이터 μ†ŒμŠ€ ID */}
handleChange("dataSourceId", e.target.value)} placeholder="λΉ„μ›Œλ‘λ©΄ URL νŒŒλΌλ―Έν„°μ—μ„œ μžλ™ μ„€μ •" className="h-7 text-xs sm:h-8 sm:text-sm" />

✨ URL νŒŒλΌλ―Έν„°μ—μ„œ μžλ™μœΌλ‘œ κ°€μ Έμ˜΅λ‹ˆλ‹€ (Button이 전달)

ν…ŒμŠ€νŠΈμš©μœΌλ‘œ 직접 μž…λ ₯ν•˜λ €λ©΄ ν…Œμ΄λΈ”λͺ…을 μž…λ ₯ν•˜μ„Έμš”

{/* πŸ†• 원본 데이터 ν…Œμ΄λΈ” */}
ν…Œμ΄λΈ”μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€. {filteredSourceTables.map((table) => ( { handleChange("sourceTable", currentValue); setSourceTableSelectOpen(false); setSourceTableSearchValue(""); if (onSourceTableChange) { onSourceTableChange(currentValue); } }} className="text-xs sm:text-sm" > {table.displayName || table.tableName} ))}

이전 ν™”λ©΄μ—μ„œ 전달받은 λ°μ΄ν„°μ˜ 원본 ν…Œμ΄λΈ” (예: item_info)

{/* μ €μž₯ λŒ€μƒ ν…Œμ΄λΈ” */}
ν…Œμ΄λΈ”μ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€. {filteredTables.map((table) => ( { handleChange("targetTable", currentValue); setTableSelectOpen(false); setTableSearchValue(""); if (onTargetTableChange) { onTargetTableChange(currentValue); } }} className="text-xs sm:text-sm" > {table.displayName || table.tableName} ))}

μ΅œμ’… 데이터λ₯Ό μ €μž₯ν•  ν…Œμ΄λΈ”

{/* ν‘œμ‹œν•  원본 데이터 컬럼 */}
{displayColumns.map((col, index) => (
))} μ‚¬μš© κ°€λŠ₯ν•œ 컬럼이 μ—†μŠ΅λ‹ˆλ‹€. {availableColumns.map((column) => ( addDisplayColumn(column.columnName, column.columnLabel || column.columnName)} className="text-xs sm:text-sm" >
{column.columnLabel || column.columnName}
{column.dataType &&
{column.dataType}
}
))}

전달받은 원본 데이터 쀑 화면에 ν‘œμ‹œν•  컬럼 (예: ν’ˆλͺ©μ½”λ“œ, ν’ˆλͺ©λͺ…)

{/* μΆ”κ°€ μž…λ ₯ ν•„λ“œ μ •μ˜ */}
{localFields.map((field, index) => (
ν•„λ“œ {index + 1}
setFieldPopoverOpen({ ...fieldPopoverOpen, [index]: open })} > μ‚¬μš© κ°€λŠ₯ν•œ 컬럼이 μ—†μŠ΅λ‹ˆλ‹€. {availableTargetColumns.map((column) => ( { updateField(index, { name: column.columnName, label: column.columnLabel || column.columnName, inputType: column.inputType || "text", // πŸ†• inputType 포함 codeCategory: column.codeCategory, // πŸ†• codeCategory 포함 }); setFieldPopoverOpen({ ...fieldPopoverOpen, [index]: false }); }} className="text-[10px] sm:text-xs" >
{column.columnLabel}
{column.columnName}
))}
updateField(index, { label: e.target.value })} placeholder="ν•„λ“œ 라벨" className="h-6 w-full text-[10px] sm:h-7 sm:text-xs" />

ν…Œμ΄λΈ” νƒ€μž…κ΄€λ¦¬μ—μ„œ μžλ™ 섀정됨

updateField(index, { placeholder: e.target.value })} placeholder="μž…λ ₯ μ•ˆλ‚΄" className="h-6 w-full text-[10px] sm:h-7 sm:text-xs" />
{/* πŸ†• 원본 데이터 μžλ™ μ±„μš°κΈ° */}
{/* ν…Œμ΄λΈ”λͺ… μž…λ ₯ */} updateField(index, { autoFillFromTable: e.target.value })} placeholder="λΉ„μ›Œλ‘λ©΄ μ£Ό 데이터 (예: item_price)" className="h-6 w-full text-[10px] sm:h-7 sm:text-xs" />

λ‹€λ₯Έ ν…Œμ΄λΈ”μ—μ„œ κ°€μ Έμ˜¬ 경우 ν…Œμ΄λΈ”λͺ… μž…λ ₯

{/* ν•„λ“œ 선택 */} 원본 ν…Œμ΄λΈ”μ„ λ¨Όμ € μ„ νƒν•˜μ„Έμš”. updateField(index, { autoFillFrom: undefined })} className="text-[10px] sm:text-xs" > 선택 μ•ˆ 함 {sourceTableColumns.map((column) => ( updateField(index, { autoFillFrom: column.columnName })} className="text-[10px] sm:text-xs" >
{column.columnLabel}
{column.columnName}
))}

{field.autoFillFromTable ? `"${field.autoFillFromTable}" ν…Œμ΄λΈ”μ—μ„œ μžλ™ μ±„μš°κΈ°` : "μ£Ό 데이터 μ†ŒμŠ€μ—μ„œ μžλ™ μ±„μš°κΈ° (μˆ˜μ • κ°€λŠ₯)" }

{/* πŸ†• ν•„λ“œ κ·Έλ£Ή 선택 */} {localFieldGroups.length > 0 && (

같은 κ·Έλ£Ή IDλ₯Ό κ°€μ§„ ν•„λ“œλ“€μ€ 같은 μΉ΄λ“œμ— ν‘œμ‹œλ©λ‹ˆλ‹€

)}
updateField(index, { required: checked as boolean })} />
))}
{/* πŸ†• ν•„λ“œ κ·Έλ£Ή 관리 */}

μΆ”κ°€ μž…λ ₯ ν•„λ“œλ₯Ό μ—¬λŸ¬ μΉ΄λ“œλ‘œ λ‚˜λˆ μ„œ ν‘œμ‹œ (예: 거래처 정보, 단가 정보)

{localFieldGroups.map((group, index) => { const isGroupExpanded = expandedGroups[group.id] ?? true; return ( setExpandedGroups(prev => ({ ...prev, [group.id]: open }))} >
{/* κ·Έλ£Ή ID */}
updateFieldGroup(group.id, { id: e.target.value })} className="h-7 text-xs sm:h-8 sm:text-sm" placeholder="group_customer" />
{/* κ·Έλ£Ή 제λͺ© */}
updateFieldGroup(group.id, { title: e.target.value })} className="h-7 text-xs sm:h-8 sm:text-sm" placeholder="거래처 정보" />
{/* κ·Έλ£Ή μ„€λͺ… */}
updateFieldGroup(group.id, { description: e.target.value })} className="h-7 text-xs sm:h-8 sm:text-sm" placeholder="거래처 κ΄€λ ¨ 정보λ₯Ό μž…λ ₯ν•©λ‹ˆλ‹€" />
{/* ν‘œμ‹œ μˆœμ„œ */}
updateFieldGroup(group.id, { order: parseInt(e.target.value) || 0 })} className="h-7 text-xs sm:h-8 sm:text-sm" min="0" />
{/* πŸ†• 이 그룹의 ν•­λͺ© ν‘œμ‹œ μ„€μ • */} setExpandedDisplayItems(prev => ({ ...prev, [group.id]: open }))} >
{/* μΆ”κ°€ λ²„νŠΌλ“€ */}

이 그룹의 μž…λ ₯ ν•­λͺ©μ΄ μΆ”κ°€λ˜λ©΄ μ–΄λ–»κ²Œ ν‘œμ‹œλ μ§€ μ„€μ •

{(!group.displayItems || group.displayItems.length === 0) ? (
λ―Έμ„€μ • (λͺ¨λ“  ν•„λ“œλ₯Ό " / "둜 κ΅¬λΆ„ν•˜μ—¬ ν‘œμ‹œ)
) : (
{group.displayItems.map((item, itemIndex) => (
{/* 헀더 */}
{item.type === "icon" && "🎨"} {item.type === "field" && "πŸ“"} {item.type === "text" && "πŸ’¬"} {item.type === "badge" && "🏷️"}
{/* μ•„μ΄μ½˜ μ„€μ • */} {item.type === "icon" && ( updateDisplayItemInGroup(group.id, itemIndex, { icon: e.target.value })} placeholder="Building" className="h-6 text-[9px] sm:text-[10px]" /> )} {/* ν…μŠ€νŠΈ μ„€μ • */} {item.type === "text" && ( updateDisplayItemInGroup(group.id, itemIndex, { value: e.target.value })} placeholder="| , / , -" className="h-6 text-[9px] sm:text-[10px]" /> )} {/* ν•„λ“œ μ„€μ • */} {item.type === "field" && (
{/* ν•„λ“œ 선택 */} {/* 라벨 */} updateDisplayItemInGroup(group.id, itemIndex, { label: e.target.value })} placeholder="라벨 (예: 거래처:)" className="h-6 w-full text-[9px] sm:text-[10px]" /> {/* ν‘œμ‹œ ν˜•μ‹ */} {/* 빈 κ°’ 처리 */} {/* κΈ°λ³Έκ°’ */} {item.emptyBehavior === "default" && ( updateDisplayItemInGroup(group.id, itemIndex, { defaultValue: e.target.value })} placeholder="λ―Έμž…λ ₯" className="h-6 w-full text-[9px] sm:text-[10px]" /> )}
)}
))}
)}
); })} {localFieldGroups.length > 0 && (

πŸ’‘ μΆ”κ°€ μž…λ ₯ ν•„λ“œμ˜ "ν•„λ“œ κ·Έλ£Ή ID"에 μœ„μ—μ„œ μ •μ˜ν•œ κ·Έλ£Ή IDλ₯Ό μž…λ ₯ν•˜μ„Έμš”

)}
{/* μž…λ ₯ λͺ¨λ“œ μ„€μ • */}

{config.inputMode === "modal" ? "μΆ”κ°€ λ²„νŠΌ 클릭 μ‹œ μž…λ ₯μ°½ ν‘œμ‹œ, μ™„λ£Œ ν›„ μž‘μ€ μΉ΄λ“œλ‘œ ν‘œμ‹œ" : "λͺ¨λ“  ν•­λͺ©μ˜ μž…λ ₯창을 항상 ν‘œμ‹œ"}

{/* λ ˆμ΄μ•„μ›ƒ μ„€μ • */}

{config.layout === "grid" ? "ν–‰ λ‹¨μœ„λ‘œ 데이터λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€" : "각 ν•­λͺ©μ„ μΉ΄λ“œλ‘œ ν‘œμ‹œν•©λ‹ˆλ‹€"}

{/* μžλ™ 계산 μ„€μ • */}
{ if (checked) { handleChange("autoCalculation", { targetField: "", mode: "template", inputFields: { basePrice: "", discountType: "", discountValue: "", roundingType: "", roundingUnit: "", }, calculationType: "price", valueMapping: {}, calculationSteps: [], }); } else { handleChange("autoCalculation", undefined); } }} />
{config.autoCalculation && (
{/* 계산 λͺ¨λ“œ 선택 */}
{/* ν…œν”Œλ¦Ώ λͺ¨λ“œ */} {config.autoCalculation.mode === "template" && ( <> {/* 계산 ν•„λ“œ 선택 */}
{/* 계산 κ²°κ³Ό ν•„λ“œ */}
{/* κΈ°μ€€ 단가 ν•„λ“œ */}
{/* 할인 방식 ν•„λ“œ */}
{/* 할인값 ν•„λ“œ */}
{/* 반올림 방식 ν•„λ“œ */}
{/* 반올림 λ‹¨μœ„ ν•„λ“œ */}
{/* μΉ΄ν…Œκ³ λ¦¬ κ°’ λ§€ν•‘ */}
{/* 할인 방식 λ§€ν•‘ */} {/* 1단계: 메뉴 선택 */}
{/* 2단계: μΉ΄ν…Œκ³ λ¦¬ 선택 */} {(config.autoCalculation.valueMapping as any)?._selectedMenus?.discountType && (
)} {/* 3단계: κ°’ λ§€ν•‘ */} {(config.autoCalculation.valueMapping as any)?._selectedCategories?.discountType && (
{["ν• μΈμ—†μŒ", "ν• μΈμœ¨(%)", "ν• μΈκΈˆμ•‘"].map((label, idx) => { const operations = ["none", "rate", "amount"]; return (
{label} β†’ {operations[idx]}
); })}
)}
{/* 반올림 방식 λ§€ν•‘ */} {/* 1단계: 메뉴 선택 */}
{/* 2단계: μΉ΄ν…Œκ³ λ¦¬ 선택 */} {(config.autoCalculation.valueMapping as any)?._selectedMenus?.roundingType && (
)} {/* 3단계: κ°’ λ§€ν•‘ */} {(config.autoCalculation.valueMapping as any)?._selectedCategories?.roundingType && (
{["λ°˜μ˜¬λ¦Όμ—†μŒ", "반올림", "μ ˆμ‚­", "올림"].map((label, idx) => { const operations = ["none", "round", "floor", "ceil"]; return (
{label} β†’ {operations[idx]}
); })}
)}
{/* 반올림 λ‹¨μœ„ λ§€ν•‘ */} {/* 1단계: 메뉴 선택 */}
{/* 2단계: μΉ΄ν…Œκ³ λ¦¬ 선택 */} {(config.autoCalculation.valueMapping as any)?._selectedMenus?.roundingUnit && (
)} {/* 3단계: κ°’ λ§€ν•‘ */} {(config.autoCalculation.valueMapping as any)?._selectedCategories?.roundingUnit && (
{["1원", "10원", "100원", "1,000원"].map((label) => { const unitValue = label === "1,000원" ? 1000 : parseInt(label); return (
{label} β†’ {unitValue}
); })}
)}

πŸ’‘ 1단계: 메뉴 선택 β†’ 2단계: μΉ΄ν…Œκ³ λ¦¬ 선택 β†’ 3단계: κ°’ λ§€ν•‘

)} {/* μ»€μŠ€ν…€ λͺ¨λ“œ (계산식 λΉŒλ”) */} {config.autoCalculation.mode === "custom" && (
{ handleChange("autoCalculation", { ...config.autoCalculation, calculationSteps: steps, }); }} />
)}
)}
{/* μ˜΅μ…˜ */}
handleChange("showIndex", checked as boolean)} />
handleChange("allowRemove", checked as boolean)} />
handleChange("disabled", checked as boolean)} />
{/* μ‚¬μš© μ˜ˆμ‹œ */}

πŸ’‘ μ‚¬μš© μ˜ˆμ‹œ

  • β€’ ν’ˆλͺ© 선택 λͺ¨λ‹¬ β†’ λ‹€μŒ λ²„νŠΌ β†’ κ±°λž˜μ²˜λ³„ 가격 μž…λ ₯
  • β€’ μ‚¬μš©μž 선택 λͺ¨λ‹¬ β†’ λ‹€μŒ λ²„νŠΌ β†’ κΆŒν•œ 및 λΆ€μ„œ ν• λ‹Ή
  • β€’ μ œν’ˆ 선택 λͺ¨λ‹¬ β†’ λ‹€μŒ λ²„νŠΌ β†’ μˆ˜λŸ‰ 및 납기일 μž…λ ₯
); }; SelectedItemsDetailInputConfigPanel.displayName = "SelectedItemsDetailInputConfigPanel";