diff --git a/client/components/KanbanBoard.tsx b/client/components/KanbanBoard.tsx new file mode 100644 index 00000000..3c532eb3 --- /dev/null +++ b/client/components/KanbanBoard.tsx @@ -0,0 +1,124 @@ +import { ReactNode } from "react"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; + +export interface KanbanColumn { + id: string; + title: string; + color: "blue" | "yellow" | "green" | "red" | "purple" | "pink" | "cyan" | "amber"; + items: KanbanItem[]; + count?: number; +} + +export interface KanbanItem { + id: string; + title: string; + subtitle?: string; + icon?: ReactNode; + badge?: string; + metadata?: Record; + onClick?: () => void; +} + +const colorMap = { + blue: "from-blue-950/40 to-blue-900/20 border-blue-500/20", + yellow: "from-yellow-950/40 to-yellow-900/20 border-yellow-500/20", + green: "from-green-950/40 to-green-900/20 border-green-500/20", + red: "from-red-950/40 to-red-900/20 border-red-500/20", + purple: "from-purple-950/40 to-purple-900/20 border-purple-500/20", + pink: "from-pink-950/40 to-pink-900/20 border-pink-500/20", + cyan: "from-cyan-950/40 to-cyan-900/20 border-cyan-500/20", + amber: "from-amber-950/40 to-amber-900/20 border-amber-500/20", +}; + +const borderMap = { + blue: "border-blue-500/10 hover:border-blue-500/30", + yellow: "border-yellow-500/10 hover:border-yellow-500/30", + green: "border-green-500/10 hover:border-green-500/30", + red: "border-red-500/10 hover:border-red-500/30", + purple: "border-purple-500/10 hover:border-purple-500/30", + pink: "border-pink-500/10 hover:border-pink-500/30", + cyan: "border-cyan-500/10 hover:border-cyan-500/30", + amber: "border-amber-500/10 hover:border-amber-500/30", +}; + +const textColorMap = { + blue: "text-blue-100", + yellow: "text-yellow-100", + green: "text-green-100", + red: "text-red-100", + purple: "text-purple-100", + pink: "text-pink-100", + cyan: "text-cyan-100", + amber: "text-amber-100", +}; + +interface KanbanBoardProps { + columns: KanbanColumn[]; + gap?: "small" | "medium" | "large"; +} + +export function KanbanBoard({ columns, gap = "medium" }: KanbanBoardProps) { + const gapClass = gap === "small" ? "gap-3" : gap === "large" ? "gap-6" : "gap-4"; + + return ( +
+ {columns.map((column) => ( + + + + {column.title} + {column.count !== undefined && ( + ({column.count}) + )} + + + + {column.items.length === 0 ? ( +
+

No items

+
+ ) : ( + column.items.map((item) => ( +
+
+ {item.icon &&
{item.icon}
} +
+

{item.title}

+ {item.subtitle && ( +

{item.subtitle}

+ )} + {item.badge && ( +
+ + {item.badge} + +
+ )} + {item.metadata && ( +
+ {Object.entries(item.metadata).map(([key, value]) => ( +
+ {key}: + {value} +
+ ))} +
+ )} +
+
+
+ )) + )} +
+
+ ))} +
+ ); +} + +export default KanbanBoard;