import { useParams, Link, useNavigate } from 'react-router-dom'; import { useBoard } from '../hooks/useBoard'; import { useCardMutations } from '../hooks/useCardMutations'; import { useListMutations } from '../hooks/useListMutations'; import { KanbanColumn } from '../components/kanban/KanbanColumn'; import { DndContext, DragEndEvent, DragOverlay, DragStartEvent, DragOverEvent, PointerSensor, useSensor, useSensors, closestCenter, } from '@dnd-kit/core'; import { Card as CardType, BoardWithDetails } from '../types/kanban'; import { useState } from 'react'; export function BoardDetail() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const { board, fetchBoard } = useBoard(parseInt(id || '0')); const { moveCard } = useCardMutations(parseInt(id || '0'), fetchBoard); const { createList } = useListMutations(parseInt(id || '0'), fetchBoard); const [activeCard, setActiveCard] = useState(null); const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 8, }, }) ); const handleDragStart = (event: DragStartEvent) => { const { active } = event; const cardId = parseInt(active.id as string); if (board) { const card = board.lists.flatMap((list) => list.cards).find((c) => c.id === cardId); if (card) { setActiveCard(card); } } }; const handleDragOver = (event: DragOverEvent) => { const { active, over } = event; if (!over) return; const activeId = parseInt(active.id as string); const overId = parseInt(over.id as string); if (activeId === overId) return; // Find the active card and its current list if (!board) return; const activeList = board.lists.find((list) => list.cards.some((card) => card.id === activeId)); // If we're hovering over a card in the same list, do nothing if (activeList) { const overCard = activeList.cards.find((card) => card.id === overId); if (overCard) return; } }; const handleDragEnd = async (event: DragEndEvent) => { const { active, over } = event; setActiveCard(null); if (!over || !board) return; const activeId = parseInt(active.id as string); const overId = parseInt(over.id as string); if (activeId === overId) return; // Find the active card let activeCard: CardType | undefined; let activeList: (typeof board.lists)[0] | undefined; for (const list of board.lists) { const card = list.cards.find((c) => c.id === activeId); if (card) { activeCard = card; activeList = list; break; } } if (!activeCard || !activeList) return; // Check if we're dropping on a list or a card const overList = board.lists.find((list) => list.id === overId); if (overList) { // Dropping on a list - append to the end if (overList.id === activeList.id) return; // Same list, do nothing await moveCard(activeCard.id, activeList.id, overList.id, overList.cards.length); return; } // Dropping on a card - find which list it belongs to let overCard: CardType | undefined; let overListContainingCard: (typeof board.lists)[0] | undefined; for (const list of board.lists) { const card = list.cards.find((c) => c.id === overId); if (card) { overCard = card; overListContainingCard = list; break; } } if (!overCard || !overListContainingCard) return; // Calculate new position const overCardIndex = overListContainingCard.cards.findIndex((c) => c.id === overId); // If dropping on the same list and after the same card, do nothing if ( overListContainingCard.id === activeList.id && overCardIndex === activeList.cards.findIndex((c) => c.id === activeId) + 1 ) { return; } await moveCard(activeCard.id, activeList.id, overListContainingCard.id, overCardIndex); }; const handleCardClick = (card: CardType) => { navigate(`/boards/${id}/cards/${card.id}`); }; const handleAddList = async () => { const listName = prompt('Enter list name:'); if (listName && listName.trim()) { try { const newList = await createList(listName.trim(), board ? board.lists.length : 0); } catch (err) { // Error handled by hook } } }; if (!board) { return
Loading...
; } return (
← Back to Boards

{board.name}

{board.description &&

{board.description}

}
Edit Board
{board.lists.map((list) => ( ))}
{activeCard ? (

{activeCard.name}

) : null}
); }