дублирование в списке и отключить копирование при открытом диалговом окне
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
SelectValue,
|
||||
} from '@/component/ui/select'
|
||||
import { ElementDefinition } from '@/entitiy/element/model/interface'
|
||||
import { useToast } from '@/lib/hooks/useToast'
|
||||
import { ElementOption } from '@/type/template'
|
||||
import { ChevronDown, Plus, Trash2 } from 'lucide-react'
|
||||
|
||||
@@ -36,6 +37,8 @@ export const selectDefinition: ElementDefinition<SelectConfig, string> = {
|
||||
return cells.map(target => ({ target, value: value || '' }))
|
||||
},
|
||||
Editor: ({ config, onChange }) => {
|
||||
const { warning } = useToast()
|
||||
|
||||
const handleAddOption = () => {
|
||||
onChange({
|
||||
...config,
|
||||
@@ -48,6 +51,19 @@ export const selectDefinition: ElementDefinition<SelectConfig, string> = {
|
||||
field: 'value' | 'label',
|
||||
value: string
|
||||
) => {
|
||||
// Проверяем дублирование только для подписей (label)
|
||||
if (field === 'label' && value.trim() !== '') {
|
||||
const isDuplicate = config.options.some(
|
||||
(option, i) =>
|
||||
i !== index &&
|
||||
option.label.trim().toLowerCase() === value.trim().toLowerCase()
|
||||
)
|
||||
if (isDuplicate) {
|
||||
warning(`Такая подпись уже существует: "${value.trim()}"`)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
onChange({
|
||||
...config,
|
||||
options: config.options.map((option, i) =>
|
||||
@@ -74,22 +90,49 @@ export const selectDefinition: ElementDefinition<SelectConfig, string> = {
|
||||
</Button>
|
||||
</div>
|
||||
<div className="max-h-32 space-y-2 overflow-y-auto">
|
||||
{config.options.map((option, index) => (
|
||||
{config.options.map((option, index) => {
|
||||
const isDuplicateLabel = config.options.some(
|
||||
(otherOption, i) =>
|
||||
i !== index &&
|
||||
option.label.trim() !== '' &&
|
||||
otherOption.label.trim().toLowerCase() ===
|
||||
option.label.trim().toLowerCase()
|
||||
)
|
||||
// Убираем проверку дублирования для значений
|
||||
const isDuplicateValue = false
|
||||
|
||||
return (
|
||||
<div key={index} className="flex gap-2">
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
placeholder="Значение"
|
||||
value={option.value}
|
||||
onChange={e =>
|
||||
handleUpdateOption(index, 'value', e.target.value)
|
||||
}
|
||||
className={isDuplicateValue ? 'border-red-500' : ''}
|
||||
/>
|
||||
{isDuplicateValue && (
|
||||
<p className="mt-1 text-xs text-red-500">
|
||||
Это значение уже используется
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<Input
|
||||
placeholder="Подпись"
|
||||
value={option.label}
|
||||
onChange={e =>
|
||||
handleUpdateOption(index, 'label', e.target.value)
|
||||
}
|
||||
className={isDuplicateLabel ? 'border-red-500' : ''}
|
||||
/>
|
||||
{isDuplicateLabel && (
|
||||
<p className="mt-1 text-xs text-red-500">
|
||||
Такая подпись уже существует
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
@@ -98,7 +141,8 @@ export const selectDefinition: ElementDefinition<SelectConfig, string> = {
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -621,6 +621,7 @@ export const ElementConstructor: React.FC<ElementConstructorProps> = ({
|
||||
onLayoutSettingsChange={onLayoutSettingsChange || (() => {})}
|
||||
onElementEdit={handleEditElement}
|
||||
onElementAdd={handleElementCopy}
|
||||
isDialogOpen={isAddDialogOpen || !!editingElement}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -25,19 +25,6 @@ const ELEMENT_MIN_SIZE: Record<string, { width: number; height: number }> = {
|
||||
button_group: { width: 180, height: 80 },
|
||||
}
|
||||
|
||||
interface VisualLayoutEditorProps {
|
||||
elements: TemplateElement[]
|
||||
layoutSettings: FormLayoutSettings
|
||||
onElementUpdate: (
|
||||
elementId: string,
|
||||
updates: Partial<TemplateElement>
|
||||
) => void
|
||||
onElementDelete: (elementId: string) => void
|
||||
onLayoutSettingsChange: (settings: FormLayoutSettings) => void
|
||||
onElementEdit?: (element: TemplateElement) => void
|
||||
onElementAdd?: (element: Omit<TemplateElement, 'id'>) => void
|
||||
}
|
||||
|
||||
interface DraggableElementProps {
|
||||
element: TemplateElement
|
||||
isSelected: boolean
|
||||
@@ -213,6 +200,20 @@ const DraggableElement: React.FC<DraggableElementProps> = React.memo(
|
||||
}
|
||||
)
|
||||
|
||||
interface VisualLayoutEditorProps {
|
||||
elements: TemplateElement[]
|
||||
layoutSettings: FormLayoutSettings
|
||||
onElementUpdate: (
|
||||
elementId: string,
|
||||
updates: Partial<TemplateElement>
|
||||
) => void
|
||||
onElementDelete: (elementId: string) => void
|
||||
onLayoutSettingsChange: (settings: FormLayoutSettings) => void
|
||||
onElementEdit?: (element: TemplateElement) => void
|
||||
onElementAdd?: (element: Omit<TemplateElement, 'id'>) => void
|
||||
isDialogOpen?: boolean // Добавляем новый проп
|
||||
}
|
||||
|
||||
export const VisualLayoutEditor: React.FC<VisualLayoutEditorProps> = ({
|
||||
elements,
|
||||
layoutSettings,
|
||||
@@ -221,6 +222,7 @@ export const VisualLayoutEditor: React.FC<VisualLayoutEditorProps> = ({
|
||||
onLayoutSettingsChange,
|
||||
onElementEdit,
|
||||
onElementAdd,
|
||||
isDialogOpen = false, // Значение по умолчанию
|
||||
}) => {
|
||||
// console.log('VisualLayoutEditor render with elements:', elements)
|
||||
const [selectedElementId, setSelectedElementId] = useState<string | null>(
|
||||
@@ -232,6 +234,11 @@ export const VisualLayoutEditor: React.FC<VisualLayoutEditorProps> = ({
|
||||
|
||||
// Обработчик клавиш для копирования/вставки
|
||||
useEffect(() => {
|
||||
// Отключаем обработчики если открыт диалог
|
||||
if (isDialogOpen) {
|
||||
return
|
||||
}
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
if (e.key === 'c' && selectedElementId) {
|
||||
@@ -248,6 +255,8 @@ export const VisualLayoutEditor: React.FC<VisualLayoutEditorProps> = ({
|
||||
...copiedElement.layout,
|
||||
x: (copiedElement.layout?.x || 0) + 20,
|
||||
y: (copiedElement.layout?.y || 0) + 20,
|
||||
width: copiedElement.layout?.width || 300,
|
||||
height: copiedElement.layout?.height || 80,
|
||||
},
|
||||
}
|
||||
delete (newElement as any).id // Удаляем id чтобы создался новый
|
||||
@@ -258,7 +267,7 @@ export const VisualLayoutEditor: React.FC<VisualLayoutEditorProps> = ({
|
||||
|
||||
document.addEventListener('keydown', handleKeyDown)
|
||||
return () => document.removeEventListener('keydown', handleKeyDown)
|
||||
}, [selectedElementId, elements, copiedElement, onElementAdd])
|
||||
}, [selectedElementId, elements, copiedElement, onElementAdd, isDialogOpen])
|
||||
|
||||
const canvasSize = useMemo(() => {
|
||||
const PADDING_Y = 200
|
||||
|
||||
Reference in New Issue
Block a user