Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Card lagging when dragging over the column #1549

Open
chertik77 opened this issue Nov 26, 2024 · 0 comments
Open

Card lagging when dragging over the column #1549

chertik77 opened this issue Nov 26, 2024 · 0 comments

Comments

@chertik77
Copy link

Screen.Recording.Nov.26.2024.mp4

// BoardColumnsList

export const BoardColumnsList = ({
  columns,
  backgroundIdentifier
}: BoardColumnsListProps) => {
  const { cards, activeCard, onDragStart, onDragOver } =
    useCardDragAndDrop(columns)

  return (
    <DndContext
      onDragStart={onDragStart}
      onDragOver={onDragOver}>
      <div className='flex gap-[34px]'>
        {columns?.map(column => (
          <BoardColumnsItem
            column={column}
            key={column.id}
            cards={cards?.filter(card => card.columnId === column.id)}
            backgroundIdentifier={backgroundIdentifier}
          />
        ))}
        <BoardAddColumnBtn />
      </div>
      {createPortal(
        <DragOverlay>
          {activeCard && <BoardCard card={activeCard!} />}
        </DragOverlay>,
        document.body
      )}
    </DndContext>
  )
}

// BoardsColumnItem

export const BoardColumnsItem = ({
  column,
  cards,
  backgroundIdentifier
}: BoardColumnsItemProps) => {
  const { open } = useModal(AddCardModal)

  const { cardPriority } = useCardFilters()

  const isTabletAndBelow = useTabletAndBelowMediaQuery()

  const filteredCards = getFilteredCardsByPriority(cards!, cardPriority)

  const cardsIds = useMemo(() => cards?.map(c => c.id), [cards])

  const { setNodeRef } = useDroppable({
    id: column.id,
    data: { type: 'column' }
  })

  return (
    <div
      className='flex w-[334px] flex-col'
      ref={setNodeRef}>
      <BoardColumnsActions column={column} />
      <ScrollArea.Root
        type='scroll'
        className={cn('-mr-4 pr-4', {
          'h-[calc(100dvh-275px)]': !isTabletAndBelow,
          'h-[calc(100dvh-300px)]': isTabletAndBelow
        })}>
        <ScrollArea.Viewport className='h-full'>
          <SortableContext items={cardsIds || []}>
            {filteredCards?.map(card => (
              <BoardCard
                card={card}
                key={card.id}
              />
            ))}
          </SortableContext>
        </ScrollArea.Viewport>
        <Scrollbar
          backgroundIdentifier={backgroundIdentifier}
          scrollBarClassName='w-2'
          thumbClassName='!w-2'
        />
      </ScrollArea.Root>
      <Button
        isPlusIcon
        className='mt-3.5'
        onClick={() => open(column.id)}>
        Add another card
      </Button>
    </div>
  )
}

// BoardCard

export const BoardCard = ({ card }: { card: Card }) => {
  const {
    setNodeRef,
    attributes,
    listeners,
    transition,
    transform,
    isDragging
  } = useSortable({
    id: card.id,
    data: { type: 'card', card }
  })

  const style = {
    transition,
    transform: CSS.Transform.toString(transform)
  }

  return isDragging ? (
    <div
      className='mb-2 h-5xl rounded-lg border-2 border-brand bg-white py-3.5 pl-6 pr-5 opacity-60
        last:mb-0 violet:border-brand-secondary dark:bg-black'
      ref={setNodeRef}
      style={style}
    />
  ) : (
    <div
      className='relative mb-2 h-5xl rounded-lg bg-white py-3.5 pl-6 pr-5 last:mb-0 dark:bg-black'
      {...listeners}
      {...attributes}
      ref={setNodeRef}
      style={style}>
      <div
        className={cn(
          'absolute left-0 top-0 h-full w-1 rounded-l',
          getPriorityColor(card.priority)
        )}
      />
      <p className='mb-2 text-base font-semibold'>{card.title}</p>
      <p className='mb-3.5 line-clamp-2 text-sm text-black/70 dark:text-white/50'>
        {card.description}
      </p>
      {/* eslint-disable-next-line tailwindcss/no-unnecessary-arbitrary-value */}
      <div className='flex items-end border-t-[1px] border-black/10 pt-3.5 dark:border-white/10'>
        <BoardCardPriority priority={card.priority} />
        <BoardCardDeadline deadline={card.deadline} />
        <BoardCardActions card={card} />
      </div>
    </div>
  )
}

// useCardDragAndDrop

export const useCardDragAndDrop = (columns: Column[] | undefined) => {
  const [cards, setCards] = useState(columns?.flatMap(c => c.cards))

  const [activeCard, setActiveCard] = useState<Card | null>(null)

  const { mutate } = useUpdateCardsOrder()

  useEffect(() => {
    setCards(columns?.flatMap(c => c.cards))
  }, [columns])

  const onDragStart = ({ active }: DragStartEvent) => {
    setActiveCard(active.data.current?.card)
  }

  const onDragOver = ({ active, over }: DragOverEvent) => {
    if (!over) return

    const activeId = active.id
    const overId = over.id

    if (!activeId || activeId === overId) return

    const isOverACard = over.data.current?.type === 'card'

    if (isOverACard) {
      setCards(cards => {
        if (!cards) return

        const activeCardIndex = cards.findIndex(card => card.id === activeId)
        const overCardIndex = cards.findIndex(card => card.id === overId)

        const activeCard = cards[activeCardIndex!]
        const overCard = cards[overCardIndex!]

        if (
          activeCard &&
          overCard &&
          activeCard.columnId !== overCard.columnId
        ) {
          activeCard.columnId = overCard.columnId

          return arrayMove(
            cards,
            activeCardIndex,
            Math.max(0, overCardIndex - 1)
          )
        }

        return arrayMove(cards, activeCardIndex, overCardIndex)
      })
    }

    const isOverAColumn = over.data.current?.type === 'column'

    if (isOverAColumn) {
      const activeCardIndex = cards?.findIndex(card => card.id === activeId)

      cards![activeCardIndex!].columnId = overId as string

      const updatedCards = arrayMove(cards!, activeCardIndex!, activeCardIndex!)

      setCards(updatedCards)

      mutate({
        columnId: overId as string,
        ids: updatedCards
          .filter(card => card.columnId === overId)
          .map(card => card.id)
      })
    }
  }

  return { cards, activeCard, onDragStart, onDragOver }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant