diff --git a/src/entitiy/element/model/implementations/StandardsElement/StandardsSelector.tsx b/src/entitiy/element/model/implementations/StandardsElement/StandardsSelector.tsx
index 2f84f05..fca8a02 100644
--- a/src/entitiy/element/model/implementations/StandardsElement/StandardsSelector.tsx
+++ b/src/entitiy/element/model/implementations/StandardsElement/StandardsSelector.tsx
@@ -9,10 +9,28 @@ import {
import { Input } from '@/component/ui/input'
import { Separator } from '@/component/ui/separator'
import { useToast } from '@/lib/hooks/useToast'
+import {
+ DndContext,
+ DragEndEvent,
+ KeyboardSensor,
+ PointerSensor,
+ closestCenter,
+ useSensor,
+ useSensors,
+} from '@dnd-kit/core'
+import {
+ SortableContext,
+ arrayMove,
+ sortableKeyboardCoordinates,
+ useSortable,
+ verticalListSortingStrategy,
+} from '@dnd-kit/sortable'
+import { CSS } from '@dnd-kit/utilities'
import {
Check,
ExternalLink,
FileText,
+ GripVertical,
Search,
Settings,
X,
@@ -21,6 +39,89 @@ import { useEffect, useMemo, useRef, useState } from 'react'
import { useStandards } from './hooks'
import { Standard } from './types'
+// Компонент для сортируемого элемента эталона
+interface SortableStandardItemProps {
+ standard: Standard
+ onRemove: (standardId: string) => void
+ isDragActive: boolean
+}
+
+function SortableStandardItem({
+ standard,
+ onRemove,
+ isDragActive,
+}: SortableStandardItemProps) {
+ const {
+ attributes,
+ listeners,
+ setNodeRef,
+ transform,
+ transition,
+ isDragging,
+ } = useSortable({ id: standard.id })
+
+ const style = {
+ transform: CSS.Transform.toString(transform),
+ transition: isDragging ? 'none' : transition,
+ opacity: isDragging ? 0.9 : 1,
+ zIndex: isDragging ? 1000 : 'auto',
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ {standard.protocol_name}
+
+
+ {standard.name}
+
+
+
+
+
+
+
+ {standard.registry_number}
+
+
+ {standard.range}
+
+
+
+
+
+ )
+}
+
interface StandardsSelectorProps {
isOpen: boolean
onClose: () => void
@@ -37,12 +138,51 @@ export function StandardsSelector({
maxItems = 7, // Значение по умолчанию
}: StandardsSelectorProps) {
const [selectedStandards, setSelectedStandards] = useState(value)
+ const [isDragActive, setIsDragActive] = useState(false)
+
+ // Синхронизируем selectedStandards с value при изменении value
+ useEffect(() => {
+ setSelectedStandards(value)
+ }, [value])
const [searchTerm, setSearchTerm] = useState('')
const { error } = useToast()
const searchInputRef = useRef(null)
const { data: standards = [], isLoading, error: apiError } = useStandards()
+ // Настройка сенсоров для drag-and-drop
+ const sensors = useSensors(
+ useSensor(PointerSensor, {
+ activationConstraint: {
+ distance: 10, // Начинать перетаскивание после движения на 10px
+ tolerance: 5,
+ delay: 100,
+ },
+ }),
+ useSensor(KeyboardSensor, {
+ coordinateGetter: sortableKeyboardCoordinates,
+ })
+ )
+
+ // Обработчик начала перетаскивания
+ const handleDragStart = () => {
+ setIsDragActive(true)
+ }
+
+ // Обработчик завершения перетаскивания
+ const handleDragEnd = (event: DragEndEvent) => {
+ const { active, over } = event
+ setIsDragActive(false)
+
+ if (over && active.id !== over.id) {
+ setSelectedStandards(items => {
+ const oldIndex = items.indexOf(active.id as string)
+ const newIndex = items.indexOf(over.id as string)
+ return arrayMove(items, oldIndex, newIndex)
+ })
+ }
+ }
+
// Автофокус на поле поиска при открытии
useEffect(() => {
if (isOpen && searchInputRef.current) {
@@ -119,9 +259,10 @@ export function StandardsSelector({
)
}, [searchTerm, standards])
- const selectedStandardsData = standards.filter(standard =>
- selectedStandards.includes(standard.id)
- )
+ // Создаем массив выбранных эталонов в том порядке, как они выбраны
+ const selectedStandardsData = selectedStandards
+ .map(standardId => standards.find(standard => standard.id === standardId))
+ .filter((standard): standard is Standard => standard !== undefined)
const unselectedStandards = filteredStandards.filter(
standard => !selectedStandards.includes(standard.id)
@@ -346,11 +487,31 @@ export function StandardsSelector({
Выбранные эталоны ({selectedStandardsData.length})
+
+ Перетащите для изменения порядка
+
- {selectedStandardsData.map(standard =>
- renderStandardCard(standard, true, true)
- )}
+
+
+ {selectedStandardsData.map(standard => (
+
+ ))}
+
+
)}