diff --git a/src/components/app/app.jsx b/src/components/app/app.jsx index 3d04b8a..3450570 100644 --- a/src/components/app/app.jsx +++ b/src/components/app/app.jsx @@ -24,7 +24,6 @@ import { getOrder, } from '../../services/actions/actions'; import BurgerConstructor from '../burger-constructor/burger-constructor'; -import { debounce } from '../../utils/utils'; function App() { const dispatch = useDispatch(); @@ -98,34 +97,24 @@ function App() { dispatch({ type: ADD_INGREDIENT, item }); }; - const findIngredient = useCallback((id) => { - const ingredient = currentBurgerIngredients.filter((c) => `${c._id}` === id)[0]; - return { - ingredient, - index: currentBurgerIngredients.indexOf(ingredient), - }; - }, [[...currentBurger].filter((item) => item.type !== 'bun')]); - - const handleMoveToDebounce = useCallback((_id, atIndex) => { - const { ingredient, index } = findIngredient(_id); + const handleMove = useCallback((dragIndex, hoverIndex) => { const bun = [...currentBurger].find((item) => item.type === 'bun'); + const dragElement = currentBurgerIngredients[dragIndex]; const payload = bun - ? [bun, update(currentBurgerIngredients, { + ? [bun, ...update(currentBurgerIngredients, { $splice: [ - [index, 1], - [atIndex, 0, ingredient], + [dragIndex, 1], + [hoverIndex, 0, dragElement], ], })] : update(currentBurgerIngredients, { $splice: [ - [index, 1], - [atIndex, 0, ingredient], + [dragIndex, 1], + [hoverIndex, 0, dragElement], ], }); dispatch({ type: MOVE_CONSTRUCTOR_ELEMENT, payload }); - }, [findIngredient, currentBurgerIngredients]); - - const handleMove = debounce(handleMoveToDebounce); + }, [currentBurgerIngredients]); const handleDeleteIngredient = (item) => { const index = currentBurger.indexOf(item); @@ -158,7 +147,6 @@ function App() { onCloseConstructor={closeConstructor} onDropHandler={handleDrop} onMove={handleMove} - findIngredient={findIngredient} onDelete={handleDeleteIngredient} /> )} diff --git a/src/components/burger-constructor/burger-constructor-element.jsx b/src/components/burger-constructor/burger-constructor-element.jsx index 9f1bb2a..3dc3fe9 100644 --- a/src/components/burger-constructor/burger-constructor-element.jsx +++ b/src/components/burger-constructor/burger-constructor-element.jsx @@ -5,48 +5,61 @@ import { ConstructorElement, DragIcon } from '@ya.praktikum/react-developer-burg import burgerConstructorStyles from './burger-constructor.module.css'; const BurgerConstructorElement = memo(({ - el, onDelete, index, onMove, findIngredient, + id, el, onDelete, index, onMove, }) => { const { - _id, name, price, image, + name, price, image, } = el; const ref = useRef(null); - const originalIndex = findIngredient(_id).index; - - const [{ isDragging }, dragRef] = useDrag(() => ({ + const [{ isDragging }, dragRef] = useDrag({ type: 'constructorElement', - item: { _id, index }, + item: () => ({ id, index }), collect: (monitor) => ({ isDragging: monitor.isDragging(), }), - end: (item, monitor) => { - // eslint-disable-next-line no-shadow - const { _id: droppedId, originalIndex } = item; - const didDrop = monitor.didDrop(); - if (!didDrop) { - onMove(droppedId, originalIndex); - } - }, - }), [_id, originalIndex, onMove]); + }); - const [, dropRef] = useDrop(() => ({ + const [{ handlerId }, dropRef] = useDrop({ accept: 'constructorElement', - hover({ _id: draggedId }) { - if (draggedId !== _id) { - const { index: overIndex } = findIngredient(_id); - onMove(draggedId, overIndex); + collect(monitor) { + return { + handlerId: monitor.getHandlerId(), + }; + }, + drop(item, monitor) { + if (!ref.current) { + return; } + const dragIndex = item.index; + const hoverIndex = index; + if (dragIndex === hoverIndex) { + return; + } + const hoverBoundingRect = ref.current?.getBoundingClientRect(); + const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2; + const clientOffset = monitor.getClientOffset(); + const hoverClientY = clientOffset.y - hoverBoundingRect.top; + if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) { + return; + } + if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) { + return; + } + onMove(dragIndex, hoverIndex); + + item.index = hoverIndex; }, - }), [findIngredient, onMove]); + }); dragRef(dropRef(ref)); return (
  • dragRef(dropRef(node))} + ref={ref} + data-handler-id={handlerId} draggable > @@ -80,7 +93,7 @@ BurgerConstructorElement.propTypes = { onDelete: PropTypes.func.isRequired, onMove: PropTypes.func.isRequired, index: PropTypes.number.isRequired, - findIngredient: PropTypes.func.isRequired, + id: PropTypes.string.isRequired, }; export default BurgerConstructorElement; diff --git a/src/components/burger-constructor/burger-constructor.jsx b/src/components/burger-constructor/burger-constructor.jsx index cafde4b..3e6f5bc 100644 --- a/src/components/burger-constructor/burger-constructor.jsx +++ b/src/components/burger-constructor/burger-constructor.jsx @@ -11,7 +11,7 @@ import BurgerConstructorMobile from './burger-constructor-mobile'; import BurgerConstructorElement from './burger-constructor-element'; function BurgerConstructor({ - onOrder, isTablet, onCloseConstructor, onDropHandler, onDelete, onMove, findIngredient, + onOrder, isTablet, onCloseConstructor, onDropHandler, onDelete, onMove, }) { const [, dropTarget] = useDrop({ accept: 'ingredient', @@ -37,11 +37,11 @@ function BurgerConstructor({ .map((el, index) => ( )), [currentBurger], @@ -114,7 +114,6 @@ BurgerConstructor.propTypes = { onDropHandler: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired, onMove: PropTypes.func.isRequired, - findIngredient: PropTypes.func.isRequired, }; export default BurgerConstructor; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 17927ba..58b3701 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -17,11 +17,3 @@ export function off( } export const isBrowser = typeof window !== 'undefined'; - -export const debounce = (fn: Function, ms = 100) => { - let timeoutId: ReturnType; - return function (this: any, ...args: any[]) { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => fn.apply(this, args), ms); - }; -};