/** * Kanban Board Component * Drag-and-drop workflow for article production */ 'use client'; import { useState } from 'react'; import { DndContext, DragEndEvent, DragOverlay, DragStartEvent, PointerSensor, useSensor, useSensors } from '@dnd-kit/core'; import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'; import { motion } from 'framer-motion'; import KanbanCard from './KanbanCard'; type ArticleStatus = 'queued' | 'generating' | 'review' | 'approved' | 'published'; interface Article { id: string; title: string; status: ArticleStatus; geo_city?: string; seo_score?: number; } interface KanbanBoardProps { articles: Article[]; onStatusChange: (articleId: string, newStatus: ArticleStatus) => void; } const columns: { id: ArticleStatus; title: string; color: string }[] = [ { id: 'queued', title: 'Queued', color: 'slate' }, { id: 'generating', title: 'Generating', color: 'electric' }, { id: 'review', title: 'Review', color: 'yellow' }, { id: 'approved', title: 'Approved', color: 'green' }, { id: 'published', title: 'Published', color: 'gold' }, ]; export default function KanbanBoard({ articles, onStatusChange }: KanbanBoardProps) { const [activeId, setActiveId] = useState(null); const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 8, }, }) ); const handleDragStart = (event: DragStartEvent) => { setActiveId(event.active.id as string); }; const handleDragEnd = (event: DragEndEvent) => { const { active, over } = event; if (!over) return; const articleId = active.id as string; const newStatus = over.id as ArticleStatus; onStatusChange(articleId, newStatus); setActiveId(null); }; const getColumnArticles = (status: ArticleStatus) => { return articles.filter(article => article.status === status); }; const activeArticle = articles.find(a => a.id === activeId); return (
{columns.map((column) => { const columnArticles = getColumnArticles(column.id); return (
{/* Column Header */}

{column.title}

{columnArticles.length}
{/* Droppable Zone */} a.id)} strategy={verticalListSortingStrategy} >
{columnArticles.map((article) => ( ))} {columnArticles.length === 0 && (

Drop here

)}
); })}
{/* Drag Overlay */} {activeArticle && ( )}
); }