162 lines
4.3 KiB
TypeScript
162 lines
4.3 KiB
TypeScript
"use client";
|
|
|
|
import { Tag, TagId, Task, TaskId, Status } from "@/lib/types";
|
|
import { Color } from "@/lib/ui/color";
|
|
import BoardView from "./board/BoardView";
|
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs";
|
|
import { TableView } from "./table/TableView";
|
|
import EditView from "./edit/EditView";
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuTrigger,
|
|
DropdownMenuSeparator,
|
|
} from "@/components/ui/dropdown-menu";
|
|
import { FileDown } from "lucide-react";
|
|
import {
|
|
downloadFile,
|
|
exportTodoAsJson,
|
|
exportTodoAsCsv,
|
|
exportTodoAsMarkdown,
|
|
} from "@/lib/export";
|
|
import { useEffect, useState } from "react";
|
|
|
|
export type TaskViewProps = {
|
|
tags: Record<TagId, Tag>;
|
|
|
|
tasks: Record<TaskId, Task>;
|
|
|
|
statuses: Status[];
|
|
|
|
/** Update entire tasks record */
|
|
setTasks: (tasks: Record<TaskId, Task>) => void;
|
|
|
|
/** Update tags */
|
|
setTags: (tags: Record<TagId, Tag>) => void;
|
|
|
|
/** Update statuses */
|
|
setStatuses: (statuses: Status[]) => void;
|
|
|
|
/** Create a new task with a status */
|
|
createTask: (statusId: string) => void;
|
|
|
|
/** Entity name for export */
|
|
entityName?: string;
|
|
};
|
|
|
|
export default function TaskView({
|
|
tags,
|
|
tasks,
|
|
statuses,
|
|
setTasks,
|
|
setTags,
|
|
setStatuses,
|
|
createTask,
|
|
entityName = "Tasks",
|
|
}: TaskViewProps) {
|
|
const [isExporting, setIsExporting] = useState(false);
|
|
|
|
const handleExport = (format: "json" | "csv" | "markdown") => {
|
|
const todoEntity = {
|
|
id: "",
|
|
type: "todo" as const,
|
|
name: entityName,
|
|
config: { statuses },
|
|
tags,
|
|
tasks,
|
|
createdAt: Date.now(),
|
|
updatedAt: Date.now(),
|
|
};
|
|
|
|
let content = "";
|
|
let filename = `${entityName.replace(/\s+/g, "_")}_${Date.now()}`;
|
|
|
|
switch (format) {
|
|
case "json":
|
|
content = exportTodoAsJson(todoEntity);
|
|
filename += ".json";
|
|
break;
|
|
case "csv":
|
|
content = exportTodoAsCsv(todoEntity);
|
|
filename += ".csv";
|
|
break;
|
|
case "markdown":
|
|
content = exportTodoAsMarkdown(todoEntity);
|
|
filename += ".md";
|
|
break;
|
|
}
|
|
|
|
downloadFile(content, filename, "text/plain");
|
|
};
|
|
return (
|
|
<div className="px-6 pt-4 flex flex-col gap-4">
|
|
<div className="flex items-center justify-end"></div>
|
|
<Tabs defaultValue="board" className="w-full">
|
|
<div className="flex justify-between">
|
|
<TabsList className="mb-4">
|
|
<TabsTrigger value="board">Board</TabsTrigger>
|
|
<TabsTrigger value="table">Table</TabsTrigger>
|
|
<TabsTrigger value="edit">Edit</TabsTrigger>
|
|
</TabsList>
|
|
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="outline" size="sm" disabled={isExporting}>
|
|
<FileDown className="h-4 w-4 mr-2" />
|
|
Export
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end">
|
|
<DropdownMenuItem onClick={() => handleExport("csv")}>
|
|
Export as CSV
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem onClick={() => handleExport("markdown")}>
|
|
Export as Markdown
|
|
</DropdownMenuItem>
|
|
<DropdownMenuSeparator />
|
|
<DropdownMenuItem onClick={() => handleExport("json")}>
|
|
Export as JSON
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</div>
|
|
|
|
<TabsContent value="board" className="mt-0">
|
|
<BoardView
|
|
tasks={tasks}
|
|
setTasks={setTasks}
|
|
createTask={createTask}
|
|
tags={tags}
|
|
setTags={setTags}
|
|
setStatuses={setStatuses}
|
|
statuses={statuses}
|
|
/>
|
|
</TabsContent>
|
|
|
|
<TabsContent value="table" className="mt-0">
|
|
<TableView
|
|
tasks={tasks}
|
|
setTasks={setTasks}
|
|
createTask={createTask}
|
|
tags={tags}
|
|
setTags={setTags}
|
|
setStatuses={setStatuses}
|
|
statuses={statuses}
|
|
/>
|
|
</TabsContent>
|
|
|
|
<TabsContent value="edit" className="mt-0">
|
|
<EditView
|
|
tags={tags}
|
|
statuses={statuses}
|
|
setTags={setTags}
|
|
setStatuses={setStatuses}
|
|
/>
|
|
</TabsContent>
|
|
</Tabs>
|
|
</div>
|
|
);
|
|
}
|