import { useState } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { cancelTodo, completeTodo, createTodo, fetchTodos } from "../api/todos"; import { PageHeader } from "../components/common/PageHeader"; import { Button } from "../components/ui/button"; import { Input } from "../components/ui/input"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../components/ui/table"; import { toast } from "sonner"; import { isApiError } from "../api/types"; import { mapApiErrorMessage } from "../api/errorMessages"; function errorMessage(error: unknown, fallback: string) { if (isApiError(error)) { return `${error.code}: ${mapApiErrorMessage(error.code, error.details, error.message)}`; } return error instanceof Error ? error.message : fallback; } export function TodosPage() { const queryClient = useQueryClient(); const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); const [statusFilter, setStatusFilter] = useState<"todo" | "doing" | "done" | "cancelled" | "">(""); const todosQuery = useQuery({ queryKey: ["todos", statusFilter], queryFn: () => fetchTodos({ status: statusFilter || undefined }), }); const createMutation = useMutation({ mutationFn: () => createTodo({ title, description: description || undefined }), onSuccess: async () => { setTitle(""); setDescription(""); await Promise.all([ queryClient.invalidateQueries({ queryKey: ["todos"] }), queryClient.invalidateQueries({ queryKey: ["portal-home"] }), ]); toast.success("待办已创建"); }, onError: (error) => toast.error(errorMessage(error, "创建待办失败")), }); const completeMutation = useMutation({ mutationFn: (id: string) => completeTodo(id), onSuccess: async () => { await Promise.all([ queryClient.invalidateQueries({ queryKey: ["todos"] }), queryClient.invalidateQueries({ queryKey: ["portal-home"] }), ]); toast.success("待办已完成"); }, onError: (error) => toast.error(errorMessage(error, "完成待办失败")), }); const cancelMutation = useMutation({ mutationFn: (id: string) => cancelTodo(id), onSuccess: async () => { await Promise.all([ queryClient.invalidateQueries({ queryKey: ["todos"] }), queryClient.invalidateQueries({ queryKey: ["portal-home"] }), ]); toast.success("待办已取消"); }, onError: (error) => toast.error(errorMessage(error, "取消待办失败")), }); return (
setTitle(event.target.value)} /> setDescription(event.target.value)} />
标题 负责人 优先级 状态 操作 {(todosQuery.data?.items ?? []).map((item) => (
{item.title}
{item.description ?? "-"}
{item.assignee?.name ?? "-"} {item.priority} {item.status}
))}
); } export default TodosPage;