/** * Exports domain hooks — draft DOCX files for a case. */ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { apiRequest } from "./client"; import { casesKeys } from "./cases"; export type ExportFile = { filename: string; size: number; created_at: number; is_final: boolean; }; export type ActiveDraft = { active_draft_path: string | null; filename: string | null; exists: boolean; }; export type Revision = { id: string; type: "insert_after" | "insert_before" | "replace" | "delete"; anchor_bookmark: string; content?: string; style?: "body" | "heading" | "quote" | "bold"; reason?: string; }; export type UploadResult = { filename: string; size: number; version: number; active_draft?: string; bookmarks_added?: string[]; missing_blocks?: string[]; apply_status?: string; }; export type ReviseResult = { status: string; output_path: string; version: number; applied: number; failed: number; results: { id: string; status: string; error?: string }[]; }; export const exportsKeys = { all: ["exports"] as const, list: (caseNumber: string) => [...exportsKeys.all, "list", caseNumber] as const, activeDraft: (caseNumber: string) => [...exportsKeys.all, "active-draft", caseNumber] as const, bookmarks: (caseNumber: string) => [...exportsKeys.all, "bookmarks", caseNumber] as const, }; export function useExports(caseNumber: string | undefined) { return useQuery({ queryKey: exportsKeys.list(caseNumber ?? ""), queryFn: ({ signal }) => apiRequest(`/api/cases/${caseNumber}/exports`, { signal }), enabled: Boolean(caseNumber), staleTime: 5_000, refetchInterval: 5_000, }); } export function useExportDocx(caseNumber: string) { const qc = useQueryClient(); return useMutation({ mutationFn: () => apiRequest<{ status: string; path: string; message: string }>( `/api/cases/${caseNumber}/export-docx`, { method: "POST" }, ), onSuccess: () => { qc.invalidateQueries({ queryKey: exportsKeys.list(caseNumber) }); qc.invalidateQueries({ queryKey: casesKeys.detail(caseNumber) }); }, }); } export function useUploadDraft(caseNumber: string) { const qc = useQueryClient(); return useMutation({ mutationFn: async (file: File): Promise => { const form = new FormData(); form.append("file", file); const res = await fetch(`/api/cases/${caseNumber}/exports/upload`, { method: "POST", body: form, }); if (!res.ok) { const err = await res.json().catch(() => ({ detail: "שגיאה בהעלאה" })); throw new Error(err.detail ?? "שגיאה בהעלאה"); } return res.json() as Promise; }, onSuccess: () => { qc.invalidateQueries({ queryKey: exportsKeys.list(caseNumber) }); qc.invalidateQueries({ queryKey: exportsKeys.activeDraft(caseNumber) }); qc.invalidateQueries({ queryKey: exportsKeys.bookmarks(caseNumber) }); }, }); } export function useActiveDraft(caseNumber: string | undefined) { return useQuery({ queryKey: exportsKeys.activeDraft(caseNumber ?? ""), queryFn: ({ signal }) => apiRequest(`/api/cases/${caseNumber}/active-draft`, { signal }), enabled: Boolean(caseNumber), staleTime: 5_000, }); } export function useBookmarks(caseNumber: string | undefined) { return useQuery({ queryKey: exportsKeys.bookmarks(caseNumber ?? ""), queryFn: ({ signal }) => apiRequest<{ status: string; active_draft_path?: string; bookmarks?: string[]; }>(`/api/cases/${caseNumber}/exports/bookmarks`, { signal }), enabled: Boolean(caseNumber), staleTime: 10_000, }); } export function useReviseDraft(caseNumber: string) { const qc = useQueryClient(); return useMutation({ mutationFn: (payload: { revisions: Revision[]; author?: string }) => apiRequest(`/api/cases/${caseNumber}/exports/revise`, { method: "POST", body: payload, }), onSuccess: () => { qc.invalidateQueries({ queryKey: exportsKeys.list(caseNumber) }); qc.invalidateQueries({ queryKey: exportsKeys.activeDraft(caseNumber) }); }, }); } export function useRetrofit(caseNumber: string) { const qc = useQueryClient(); return useMutation({ mutationFn: (filename: string) => apiRequest<{ status: string; active_draft_path: string; bookmarks_added: string[]; missing_blocks: string[]; }>(`/api/cases/${caseNumber}/exports/${filename}/retrofit`, { method: "POST", }), onSuccess: () => { qc.invalidateQueries({ queryKey: exportsKeys.activeDraft(caseNumber) }); qc.invalidateQueries({ queryKey: exportsKeys.bookmarks(caseNumber) }); }, }); } export function useDeleteDraft(caseNumber: string) { const qc = useQueryClient(); return useMutation({ mutationFn: (filename: string) => apiRequest<{ deleted: boolean; filename: string }>( `/api/cases/${caseNumber}/exports/${filename}`, { method: "DELETE" }, ), onSuccess: () => { qc.invalidateQueries({ queryKey: exportsKeys.list(caseNumber) }); }, }); } export function useMarkFinal(caseNumber: string) { const qc = useQueryClient(); return useMutation({ mutationFn: (filename: string) => apiRequest<{ final_filename: string; status: string }>( `/api/cases/${caseNumber}/exports/${filename}/mark-final`, { method: "POST" }, ), onSuccess: () => { qc.invalidateQueries({ queryKey: exportsKeys.list(caseNumber) }); qc.invalidateQueries({ queryKey: casesKeys.detail(caseNumber) }); }, }); }