import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import type { CreateMaterialRequest, Material, MaterialListResponse, MaterialResponse, MaterialStatus, } from "../../../shared/api"; import { handleResponse, handleVoidResponse } from "../utils/api"; import { createConsoleLogger } from "../utils/logger"; const MATERIALS_KEY = ["materials"] as const; const logger = createConsoleLogger(); export function createMaterial(args: { body: CreateMaterialRequest; projectId: string }): Promise { const response = fetch(`/api/projects/${args.projectId}/materials`, { body: JSON.stringify(args.body), headers: { "Content-Type": "application/json" }, method: "POST", }); return response.then((r) => handleResponse(r, (data) => (data as MaterialResponse).material)); } export function approveMaterial(args: { materialId: string; projectId: string }): Promise { const response = fetch(`/api/projects/${args.projectId}/materials/${args.materialId}/approve`, { method: "POST" }); return response.then((r) => handleResponse(r, (data) => (data as MaterialResponse).material)); } export function deleteMaterial(args: { materialId: string; projectId: string }): Promise { const response = fetch(`/api/projects/${args.projectId}/materials/${args.materialId}`, { method: "DELETE" }); return response.then(handleVoidResponse); } export function discardMaterial(args: { materialId: string; projectId: string }): Promise { const response = fetch(`/api/projects/${args.projectId}/materials/${args.materialId}/discard`, { method: "POST" }); return response.then((r) => handleResponse(r, (data) => (data as MaterialResponse).material)); } export function retryMaterial(args: { materialId: string; projectId: string }): Promise { const response = fetch(`/api/projects/${args.projectId}/materials/${args.materialId}/retry`, { method: "POST" }); return response.then((r) => handleResponse(r, (data) => (data as MaterialResponse).material)); } export async function fetchMaterial(args: { materialId: string; projectId: string }): Promise { const response = await fetch(`/api/projects/${args.projectId}/materials/${args.materialId}`); return handleResponse(response, (data) => (data as MaterialResponse).material); } export function fetchMaterials( projectId: string, params?: { page?: number; pageSize?: number; status?: MaterialStatus }, ): 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?.status) searchParams.set("status", params.status); const qs = searchParams.toString(); const url = `/api/projects/${projectId}/materials${qs ? `?${qs}` : ""}`; const response = fetch(url); return response.then((r) => { if (!r.ok) { return r.json().then((body: null | { error?: string }) => { throw new Error(body?.error ?? `HTTP ${r.status}`); }); } return r.json() as Promise; }); } export function useCreateMaterial(projectId: string) { const queryClient = useQueryClient(); return useMutation({ mutationFn: createMaterial, onSuccess: (data) => { logger.info("素材创建成功", { materialId: data.id, projectId }); void queryClient.invalidateQueries({ queryKey: [...MATERIALS_KEY, "list", projectId] }); }, }); } export function useApproveMaterial(projectId: string) { const queryClient = useQueryClient(); return useMutation({ mutationFn: approveMaterial, onSuccess: (data) => { logger.info("素材通过成功", { materialId: data.id, projectId }); void queryClient.invalidateQueries({ queryKey: [...MATERIALS_KEY, "list", projectId] }); void queryClient.invalidateQueries({ queryKey: [...MATERIALS_KEY, "detail", projectId, data.id] }); }, }); } export function useDeleteMaterial(projectId: string) { const queryClient = useQueryClient(); return useMutation({ mutationFn: deleteMaterial, onSuccess: (_data, variables) => { logger.info("素材删除成功", { materialId: variables.materialId, projectId }); void queryClient.invalidateQueries({ queryKey: [...MATERIALS_KEY, "list", projectId] }); }, }); } export function useDiscardMaterial(projectId: string) { const queryClient = useQueryClient(); return useMutation({ mutationFn: discardMaterial, onSuccess: (data) => { logger.info("素材放弃成功", { materialId: data.id, projectId }); void queryClient.invalidateQueries({ queryKey: [...MATERIALS_KEY, "list", projectId] }); void queryClient.invalidateQueries({ queryKey: [...MATERIALS_KEY, "detail", projectId, data.id] }); }, }); } export function useRetryMaterial(projectId: string) { const queryClient = useQueryClient(); return useMutation({ mutationFn: retryMaterial, onSuccess: (data) => { logger.info("素材重试成功", { materialId: data.id, projectId }); void queryClient.invalidateQueries({ queryKey: [...MATERIALS_KEY, "list", projectId] }); void queryClient.invalidateQueries({ queryKey: [...MATERIALS_KEY, "detail", projectId, data.id] }); }, }); } export function useMaterial(args: { materialId: null | string; projectId: string }) { return useQuery({ enabled: !!args.materialId, queryFn: () => fetchMaterial({ materialId: args.materialId!, projectId: args.projectId }), queryKey: [...MATERIALS_KEY, "detail", args.projectId, args.materialId], }); } export function useMaterialList( projectId: string, params?: { page?: number; pageSize?: number; status?: MaterialStatus }, ) { return useQuery({ queryFn: () => fetchMaterials(projectId, params), queryKey: [...MATERIALS_KEY, "list", projectId, params], }); }