Drag & Drop

On part de la base de code du TD front-end. Vous trouverez à l'intérieur du fichier main.jsx un code pour react-query qui donnait le contexte avec QueryClientProvider. On va faire la même chose mais pour le drag & drop afin que deux composants puissent comuniquer ensemble sans savoir qui sont les deux.

Installation

Installer la librairie dnd-kit :

		npm i @dnd-kit/core
	

Puis on ajoute le contexte dans le App.jx, on met le contexte autour des tâches comme ça ce contexte là ne concernera que les tâches et les colonnes. Ça nous facilitera la vie :

src/app.jsx
		// ...
import { DndContext } from '@dnd-kit/core'
 
function App() {
  // ...
  return (
    // ...
    <DndContext>
      // .map des tâches
    </DndContext>
    // ...
  )
}
	

Création de notre premier droppable

Pour créer un droppable, on va utiliser le hook useDroppable.

Column.jsx
		import { useDroppable } from '@dnd-kit/core'
 
export function Column({ status, tasks }) {
	const { setNodeRef } = useDroppable({ id: status })
 
  return <div ref={setNodeRef} className="flex flex-col gap-4">
    <h2 className="text-lg font-bold">{status}</h2>
    <div className="border rounded-lg grow p-4">
      <ul className="flex flex-col gap-4">
        {tasks.map((task) => {
          return <Task key={task.id} task={task} />;
        })}
      </ul>
    </div>
  </div>
}
	

Création de notre premier draggable

Pour créer un draggable, on va utiliser le hook useDraggable.

Task.jsx
		import { useDraggable } from '@dnd-kit/core'
 
export function Task({ task }) {
  const { attributes, listeners, setNodeRef, transform } = useDraggable({ id: task.id })
 
  const style = transform ? {
    transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
  } : undefined
 
  return <li key={task.id} className="border rounded-lg p-4" ref={setNodeRef} style={style} {...listeners} {...attributes}>
    <h3 className="font-bold">{task.title}</h3>
    <p>{task.description}</p>
  </li>
}
	

Pour tester que ça marche, on peut récupérer le isOver du droppable pour voir si un draggable est sur le droppable.

Column.jsx
		import { useDroppable } from '@dnd-kit/core'
 
export function Column({ status, tasks }) {
	const { setNodeRef, isOver } = useDroppable({ id: status })
 
  const style = {
    backgroundColor: isOver ? 'red' : 'white',
  }
 
  return <div ref={setNodeRef} className="flex flex-col gap-4" style={style}>
    // ...
  </div>
}
	

Testons les événements drag & drop

Pour tester les événements, on va retourner dans le DndContext, et on va utiliser l'événement onDragEnd, qui est l'événement qui est lancé lorsque le draggable est droppé.

App.jsx
		import { DndContext } from '@dnd-kit/core'
 
function App() {
 
  const handleDragEnd = (event) => {
    console.log(event)
    console.log(`La ${event.active.id} a été drop sur ${event.over.id}`)
  }
 
 
  // ...
  return (
    // ...
    <DndContext onDragEnd={handleDragEnd}>
	

Ici, lorsqu'on drop une tâche sur une colonne, on va logguer l'id de la tâche et l'id de la colonne.