118 lines
2.8 KiB
TypeScript
118 lines
2.8 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import { useState } from "react";
|
||
|
|
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
|
||
|
|
import {
|
||
|
|
KanbanBoard,
|
||
|
|
KanbanCard,
|
||
|
|
KanbanCards,
|
||
|
|
KanbanHeader,
|
||
|
|
KanbanProvider,
|
||
|
|
} from "~/components/ui/kanban";
|
||
|
|
|
||
|
|
const columns = [
|
||
|
|
{ id: "todo", name: "To Do", color: "red" },
|
||
|
|
{ id: "inprogress", name: "In Progress", color: "blue" },
|
||
|
|
{ id: "done", name: "Done", color: "green" },
|
||
|
|
];
|
||
|
|
const exampleFeatures = [
|
||
|
|
{
|
||
|
|
id: "1",
|
||
|
|
name: "Design new homepage",
|
||
|
|
column: "todo",
|
||
|
|
startAt: new Date("2024-06-01"),
|
||
|
|
endAt: new Date("2024-06-10"),
|
||
|
|
owner: {
|
||
|
|
name: "Alice",
|
||
|
|
image: "https://i.pravatar.cc/150?img=1",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: "2",
|
||
|
|
name: "Implement authentication",
|
||
|
|
column: "inprogress",
|
||
|
|
startAt: new Date("2024-06-05"),
|
||
|
|
endAt: new Date("2024-06-15"),
|
||
|
|
owner: {
|
||
|
|
name: "Bob",
|
||
|
|
image: "https://i.pravatar.cc/150?img=2",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: "3",
|
||
|
|
name: "Set up database",
|
||
|
|
column: "done",
|
||
|
|
startAt: new Date("2024-05-20"),
|
||
|
|
endAt: new Date("2024-05-30"),
|
||
|
|
owner: {
|
||
|
|
name: "Charlie",
|
||
|
|
image: "https://i.pravatar.cc/150?img=3",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
const dateFormatter = new Intl.DateTimeFormat("en-US", {
|
||
|
|
month: "short",
|
||
|
|
day: "numeric",
|
||
|
|
year: "numeric",
|
||
|
|
});
|
||
|
|
const shortDateFormatter = new Intl.DateTimeFormat("en-US", {
|
||
|
|
month: "short",
|
||
|
|
day: "numeric",
|
||
|
|
});
|
||
|
|
const Example = () => {
|
||
|
|
const [features, setFeatures] = useState(exampleFeatures);
|
||
|
|
return (
|
||
|
|
<KanbanProvider
|
||
|
|
columns={columns}
|
||
|
|
data={features}
|
||
|
|
onDataChange={setFeatures}
|
||
|
|
>
|
||
|
|
{(column) => (
|
||
|
|
<KanbanBoard id={column.id} key={column.id}>
|
||
|
|
<KanbanHeader>
|
||
|
|
<div className="flex items-center gap-2">
|
||
|
|
<div
|
||
|
|
className="h-2 w-2 rounded-full"
|
||
|
|
style={{ backgroundColor: column.color }}
|
||
|
|
/>
|
||
|
|
<span>{column.name}</span>
|
||
|
|
</div>
|
||
|
|
</KanbanHeader>
|
||
|
|
<KanbanCards id={column.id}>
|
||
|
|
{(feature: (typeof features)[number]) => (
|
||
|
|
<KanbanCard
|
||
|
|
column={column.id}
|
||
|
|
id={feature.id}
|
||
|
|
key={feature.id}
|
||
|
|
name={feature.name}
|
||
|
|
>
|
||
|
|
<div className="flex items-start justify-between gap-2">
|
||
|
|
<div className="flex flex-col gap-1">
|
||
|
|
<p className="m-0 flex-1 font-medium text-sm">
|
||
|
|
{feature.name}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
{feature.owner && (
|
||
|
|
<Avatar className="h-4 w-4 shrink-0">
|
||
|
|
<AvatarImage src={feature.owner.image} />
|
||
|
|
<AvatarFallback>
|
||
|
|
{feature.owner.name?.slice(0, 2)}
|
||
|
|
</AvatarFallback>
|
||
|
|
</Avatar>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
<p className="m-0 text-muted-foreground text-xs">
|
||
|
|
{shortDateFormatter.format(feature.startAt)} -{" "}
|
||
|
|
{dateFormatter.format(feature.endAt)}
|
||
|
|
</p>
|
||
|
|
</KanbanCard>
|
||
|
|
)}
|
||
|
|
</KanbanCards>
|
||
|
|
</KanbanBoard>
|
||
|
|
)}
|
||
|
|
</KanbanProvider>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
export default Example;
|