import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import type { CreateProjectRequest, Project, ProjectListResponse, ProjectResponse, ProjectStatus, UpdateProjectRequest, } from "../../../shared/api"; import { handleResponse, handleVoidResponse } from "../utils/api"; import { createConsoleLogger } from "../utils/logger"; const PROJECTS_KEY = ["projects"] as const; const logger = createConsoleLogger(); export async function archiveProject(id: string): Promise { const response = await fetch(`/api/projects/${id}/archive`, { method: "POST" }); return handleResponse(response, (data) => (data as ProjectResponse).project); } export async function createProject(data: CreateProjectRequest): Promise { const response = await fetch("/api/projects", { body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, method: "POST", }); return handleResponse(response, (data) => (data as ProjectResponse).project); } export async function deleteProject(id: string): Promise { const response = await fetch(`/api/projects/${id}`, { method: "DELETE" }); return handleVoidResponse(response); } export async function fetchProject(id: string): Promise { const response = await fetch(`/api/projects/${id}`); return handleResponse(response, (data) => (data as ProjectResponse).project); } export async function fetchProjectList(params: { keyword?: string; page?: number; pageSize?: number; sortBy?: string; sortOrder?: string; status?: ProjectStatus; }): Promise { const searchParams = new URLSearchParams(); if (params.page) searchParams.set("page", String(params.page)); if (params.pageSize) searchParams.set("pageSize", String(params.pageSize)); if (params.keyword) searchParams.set("keyword", params.keyword); if (params.sortBy) searchParams.set("sortBy", params.sortBy); if (params.sortOrder) searchParams.set("sortOrder", params.sortOrder); if (params.status) searchParams.set("status", params.status); const qs = searchParams.toString(); const url = `/api/projects${qs ? `?${qs}` : ""}`; const response = await fetch(url); if (!response.ok) { const body = (await response.json().catch(() => null)) as null | { error?: string }; throw new Error(body?.error ?? `HTTP ${response.status}`); } return response.json() as Promise; } export async function restoreProject(id: string): Promise { const response = await fetch(`/api/projects/${id}/restore`, { method: "POST" }); return handleResponse(response, (data) => (data as ProjectResponse).project); } export async function updateProject(id: string, data: UpdateProjectRequest): Promise { const response = await fetch(`/api/projects/${id}`, { body: JSON.stringify(data), headers: { "Content-Type": "application/json" }, method: "PATCH", }); return handleResponse(response, (data) => (data as ProjectResponse).project); } export function useArchiveProject() { const queryClient = useQueryClient(); return useMutation({ mutationFn: archiveProject, onSuccess: (data) => { logger.info("项目归档成功", { name: data.name, projectId: data.id }); void queryClient.invalidateQueries({ queryKey: PROJECTS_KEY }); }, }); } export function useCreateProject() { const queryClient = useQueryClient(); return useMutation({ mutationFn: createProject, onSuccess: (data) => { logger.info("项目创建成功", { name: data.name, projectId: data.id }); void queryClient.invalidateQueries({ queryKey: PROJECTS_KEY }); }, }); } export function useDeleteProject() { const queryClient = useQueryClient(); return useMutation({ mutationFn: deleteProject, onSuccess: (_data, variables) => { logger.info("项目删除成功", { projectId: variables }); void queryClient.invalidateQueries({ queryKey: PROJECTS_KEY }); }, }); } export function useProject(id: string) { return useQuery({ enabled: !!id, queryFn: () => fetchProject(id), queryKey: [...PROJECTS_KEY, "detail", id], }); } export function useProjectList(params: { keyword?: string; page?: number; pageSize?: number; sortBy?: string; sortOrder?: string; status?: ProjectStatus; }) { return useQuery({ queryFn: () => fetchProjectList(params), queryKey: [...PROJECTS_KEY, "list", params], }); } export function useRestoreProject() { const queryClient = useQueryClient(); return useMutation({ mutationFn: restoreProject, onSuccess: (data) => { logger.info("项目恢复成功", { name: data.name, projectId: data.id }); void queryClient.invalidateQueries({ queryKey: PROJECTS_KEY }); }, }); } export function useUpdateProject() { const queryClient = useQueryClient(); return useMutation({ mutationFn: (args: { data: UpdateProjectRequest; id: string }) => updateProject(args.id, args.data), onSuccess: (data) => { logger.info("项目更新成功", { name: data.name, projectId: data.id }); void queryClient.invalidateQueries({ queryKey: PROJECTS_KEY }); }, }); }