feat: add board view with columns, headers, and inline card creation
This commit is contained in:
72
src/components/board/KanbanColumn.tsx
Normal file
72
src/components/board/KanbanColumn.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import { useState } from "react";
|
||||
import { Plus } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { ColumnHeader } from "@/components/board/ColumnHeader";
|
||||
import { AddCardInput } from "@/components/board/AddCardInput";
|
||||
import { CardThumbnail } from "@/components/board/CardThumbnail";
|
||||
import { useBoardStore } from "@/stores/board-store";
|
||||
import type { Column } from "@/types/board";
|
||||
|
||||
const WIDTH_MAP = {
|
||||
narrow: 180,
|
||||
standard: 280,
|
||||
wide: 360,
|
||||
} as const;
|
||||
|
||||
interface KanbanColumnProps {
|
||||
column: Column;
|
||||
}
|
||||
|
||||
export function KanbanColumn({ column }: KanbanColumnProps) {
|
||||
const [showAddCard, setShowAddCard] = useState(false);
|
||||
const board = useBoardStore((s) => s.board);
|
||||
|
||||
const width = WIDTH_MAP[column.width];
|
||||
|
||||
return (
|
||||
<div
|
||||
className="group/column flex shrink-0 flex-col rounded-lg bg-pylon-column"
|
||||
style={{ width }}
|
||||
>
|
||||
<ColumnHeader column={column} cardCount={column.cardIds.length} />
|
||||
|
||||
{/* Card list */}
|
||||
<ScrollArea className="flex-1 overflow-y-auto">
|
||||
<div className="flex flex-col gap-2 p-2">
|
||||
{column.cardIds.map((cardId) => {
|
||||
const card = board?.cards[cardId];
|
||||
if (!card) return null;
|
||||
return (
|
||||
<CardThumbnail
|
||||
key={cardId}
|
||||
card={card}
|
||||
boardLabels={board?.labels ?? []}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
|
||||
{/* Add card section */}
|
||||
{showAddCard ? (
|
||||
<AddCardInput
|
||||
columnId={column.id}
|
||||
onClose={() => setShowAddCard(false)}
|
||||
/>
|
||||
) : (
|
||||
<div className="p-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setShowAddCard(true)}
|
||||
className="w-full justify-start text-pylon-text-secondary hover:text-pylon-text"
|
||||
>
|
||||
<Plus className="size-4" />
|
||||
Add card
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user