From d07df3b042862adde50988e673116335435e8a14 Mon Sep 17 00:00:00 2001 From: eyob-muktar Date: Fri, 22 Dec 2023 17:00:59 +0300 Subject: [PATCH 1/3] install react-dnd and html-backend --- package.json | 6 ++++-- yarn.lock | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 88e72a8..5260d65 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "prop-types": "^15.7.2", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.0", + "react-dnd": "^16.0.1", + "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", "react-redux": "^7.2.4", "react-to-print": "^2.12.4", @@ -38,9 +40,9 @@ "sass": "^1.32.12", "sonner": "^1.2.4", "swr": "^0.5.6", + "tailwindcss": "^3.3.6", "uuid": "^8.3.2", - "yup": "^0.32.9", - "tailwindcss": "^3.3.6" + "yup": "^0.32.9" }, "devDependencies": { "@next/eslint-plugin-next": "^13.4.19", diff --git a/yarn.lock b/yarn.lock index 1bfa251..d3df067 100644 --- a/yarn.lock +++ b/yarn.lock @@ -502,6 +502,21 @@ tslib "^2.4.1" webcrypto-core "^1.7.4" +"@react-dnd/asap@^5.0.1": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@react-dnd/asap/-/asap-5.0.2.tgz#1f81f124c1cd6f39511c11a881cfb0f715343488" + integrity sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A== + +"@react-dnd/invariant@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@react-dnd/invariant/-/invariant-4.0.2.tgz#b92edffca10a26466643349fac7cdfb8799769df" + integrity sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw== + +"@react-dnd/shallowequal@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz#d1b4befa423f692fa4abf1c79209702e7d8ae4b4" + integrity sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA== + "@rushstack/eslint-patch@^1.1.3": version "1.3.3" resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.3.tgz" @@ -2233,6 +2248,15 @@ dlv@^1.1.3: resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== +dnd-core@^16.0.1: + version "16.0.1" + resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-16.0.1.tgz#a1c213ed08961f6bd1959a28bb76f1a868360d19" + integrity sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng== + dependencies: + "@react-dnd/asap" "^5.0.1" + "@react-dnd/invariant" "^4.0.1" + redux "^4.2.0" + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz" @@ -5638,6 +5662,24 @@ react-beautiful-dnd@^13.1.0: redux "^4.0.4" use-memo-one "^1.1.1" +react-dnd-html5-backend@^16.0.1: + version "16.0.1" + resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-16.0.1.tgz#87faef15845d512a23b3c08d29ecfd34871688b6" + integrity sha512-Wu3dw5aDJmOGw8WjH1I1/yTH+vlXEL4vmjk5p+MHxP8HuHJS1lAGeIdG/hze1AvNeXWo/JgULV87LyQOr+r5jw== + dependencies: + dnd-core "^16.0.1" + +react-dnd@^16.0.1: + version "16.0.1" + resolved "https://registry.yarnpkg.com/react-dnd/-/react-dnd-16.0.1.tgz#2442a3ec67892c60d40a1559eef45498ba26fa37" + integrity sha512-QeoM/i73HHu2XF9aKksIUuamHPDvRglEwdHL4jsp784BgUuWcg6mzfxT0QDdQz8Wj0qyRKx2eMg8iZtWvU4E2Q== + dependencies: + "@react-dnd/invariant" "^4.0.1" + "@react-dnd/shallowequal" "^4.0.1" + dnd-core "^16.0.1" + fast-deep-equal "^3.1.3" + hoist-non-react-statics "^3.3.2" + react-dom@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" @@ -5766,6 +5808,13 @@ redux@^4.0.0, redux@^4.0.4, redux@^4.1.0: dependencies: "@babel/runtime" "^7.9.2" +redux@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== + dependencies: + "@babel/runtime" "^7.9.2" + reflect.getprototypeof@^1.0.3: version "1.0.4" resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz" From c5f0ee99a3834c8f4dc7a1e894a063c46cf138c4 Mon Sep 17 00:00:00 2001 From: eyob-muktar Date: Fri, 22 Dec 2023 17:22:19 +0300 Subject: [PATCH 2/3] added a react-dnd wrapper and draggable card --- components/LeftSideBar.js | 34 ++++++++------- components/drag&drop/DraggableCard.js | 59 +++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 15 deletions(-) create mode 100644 components/drag&drop/DraggableCard.js diff --git a/components/LeftSideBar.js b/components/LeftSideBar.js index 44b0420..077f72e 100644 --- a/components/LeftSideBar.js +++ b/components/LeftSideBar.js @@ -8,6 +8,8 @@ import React from 'react'; import { useSelector } from 'react-redux'; // import ArrowBackIcon from '@material-ui/icons/ArrowBack'; // import EditSingleExperience from "./forms/EditSingleExperience" +import { DndProvider } from 'react-dnd'; +import { HTML5Backend } from 'react-dnd-html5-backend'; import ReorderEducation from './drag&drop/ReorderEducation'; import ReorderExperience from './drag&drop/ReorderExperience'; import ReorderExtras from './drag&drop/ReorderExtras'; @@ -54,21 +56,23 @@ const LeftSideBar = () => { ); return ( -
- {/* add overflow-scroll ||^^ if section are needed to scroll */} - {sections.data.map(({ title, Icon, id, label }) => ( -
- - - - - {leftList(label)} - -
- ))} -
+ +
+ {/* add overflow-scroll ||^^ if section are needed to scroll */} + {sections.data.map(({ title, Icon, id, label }) => ( +
+ + + + + {leftList(label)} + +
+ ))} +
+
); }; diff --git a/components/drag&drop/DraggableCard.js b/components/drag&drop/DraggableCard.js new file mode 100644 index 0000000..f5669a4 --- /dev/null +++ b/components/drag&drop/DraggableCard.js @@ -0,0 +1,59 @@ +/* eslint-disable react/display-name */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +import { memo } from 'react'; +import { useDrag, useDrop } from 'react-dnd'; + +export const DraggableCard = memo(({ onClickItem, children, id, moveCard, findCard }) => { + const originalIndex = findCard(id).index; + + const [{ isDragging }, drag] = useDrag( + () => ({ + type: 'card', + item: { id, originalIndex }, + collect: monitor => ({ + isDragging: monitor.isDragging(), + }), + end: (item, monitor) => { + const { id: droppedId, originalIndex } = item; + const didDrop = monitor.didDrop(); + if (!didDrop) { + moveCard(droppedId, originalIndex); + } + }, + }), + [id, originalIndex, moveCard], + ); + + const [, drop] = useDrop( + () => ({ + accept: 'card', + hover({ id: draggedId }) { + if (draggedId !== id) { + const { index: overIndex } = findCard(id); + moveCard(draggedId, overIndex); + } + }, + }), + [findCard, moveCard], + ); + + const grid = 10; + const getItemStyle = isDragging => ({ + padding: grid * 2, + marginBottom: `${grid}px`, + background: '#1abc9c', + opacity: isDragging ? 0 : 1, + cursor: 'move', + }); + return ( +
onClickItem({ id })} + className="text-white text-lg bg-primary rounded" + ref={node => drag(drop(node))} + style={{ ...getItemStyle(isDragging) }} + > + {children} +
+ ); +}); From 61545a9bd48a8c766a79b0ff6194606a6dc3b77e Mon Sep 17 00:00:00 2001 From: eyob-muktar Date: Fri, 22 Dec 2023 17:23:26 +0300 Subject: [PATCH 3/3] replaced react-beautiful-dnd with react-dnd --- components/drag&drop/ReorderEducation.js | 147 +++++++++++------------ 1 file changed, 68 insertions(+), 79 deletions(-) diff --git a/components/drag&drop/ReorderEducation.js b/components/drag&drop/ReorderEducation.js index 508efa0..f120f8c 100644 --- a/components/drag&drop/ReorderEducation.js +++ b/components/drag&drop/ReorderEducation.js @@ -1,3 +1,5 @@ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ import { useAuth } from '@clerk/nextjs'; import { Drawer, makeStyles, useMediaQuery } from '@material-ui/core'; import Button from '@material-ui/core/Button'; @@ -6,8 +8,8 @@ import ArrowBackIcon from '@material-ui/icons/ArrowBack'; import SaveIcon from '@material-ui/icons/Save'; import axios from 'axios'; import clsx from 'clsx'; -import React, { useEffect, useState } from 'react'; -import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useDrop } from 'react-dnd'; import { useDispatch, useSelector } from 'react-redux'; import { toast } from 'sonner'; import { v4 as uuidv4 } from 'uuid'; @@ -16,6 +18,7 @@ import { toastMessages } from '../../shared/contants'; import { EmptyFileSVG } from '../SVGs'; import EducationCard from '../cards/EducationCard'; import EditSingleEducation from '../forms/EditSingleEducation'; +import { DraggableCard } from './DraggableCard'; const ReorderEducation = ({ closeDrawer, anchor, type }) => { const { getToken } = useAuth(); @@ -85,29 +88,32 @@ const ReorderEducation = ({ closeDrawer, anchor, type }) => { const toggleEduDrawerStates = (id, open) => event => { setEduDrawerStates({ ...eduDrawerStates, [id]: open }); }; - const onDragEnd = result => { - if (!result.destination) return; - const items = Array.from(edu); - const [reorderItem] = items.splice(result.source.index, 1); - items.splice(result.destination.index, 0, reorderItem); - setEdu(items); - }; - - const grid = 10; - const getItemStyle = (isDragging, draggableStyle) => ({ - // some basic styles to make the items look a bit nicer - userSelect: 'none', - padding: grid * 2, - margin: `0 0 ${grid}px 0`, - transition: 'height 0.2s', - overflow: 'hidden', - - // change background colour if dragging - background: isDragging ? '#1abc9c95' : '#1abc9c', - - // styles we need to apply on draggables - ...draggableStyle, - }); + const findCard = useCallback( + id => { + const card = edu.filter(c => `${c.id}` === id)[0]; + return { + card, + index: edu.indexOf(card), + }; + }, + [edu], + ); + const moveCard = useCallback( + (id, atIndex) => { + const { card, index } = findCard(id); + const items = Array.from(edu); + const [reorderItem] = items.splice(index, 1); + items.splice(atIndex, 0, reorderItem); + setEdu(items); + }, + [findCard, edu, setEdu], + ); + const [{ didDrop }, drop] = useDrop(() => ({ + accept: 'card', + collect: monitor => ({ + didDrop: monitor.didDrop(), + }), + })); const getListStyle = isDraggingOver => ({ // background: isDraggingOver ? '#ffffff' : '#16a085', @@ -248,64 +254,47 @@ const ReorderEducation = ({ closeDrawer, anchor, type }) => {

Add Education

- - - - {(provided, snapshot) => ( - // eslint-disable-next-line -
{ - if (snapshot.isDraggingOver) { - disableActiveEdu(); - } - }} - > - {edu.length === 0 ? ( -
-
- -
No Education Yet!
-
-
- ) : ( - edu.map((e, index) => ( - - {(provided, snapshot) => ( - // eslint-disable-next-line -
onClickEdu({ id: e.id })} - className="p-6 text-white text-lg bg-primary rounded" - {...provided.draggableProps} - {...provided.dragHandleProps} - ref={provided.innerRef} - style={{ - ...getItemStyle(snapshot.isDragging, provided.draggableProps.style), - }} - > - -
- )} -
- )) - )} - {provided.placeholder} -
- )} -
-
+ + {edu.length === 0 ? ( +
+
+ +
No Education Yet!
+
+
+ ) : ( +
{ + if (didDrop) { + disableActiveEdu(); + } + }} + > + {edu.map((e, index) => ( + + + + ))} +
+ )} {edu.map(edu => (