/** * Hook for managing context documents with basic fetch operations */ import { useState, useCallback } from "react"; import { ContextDocument, CreateContextRequest, UpdateContextRequest, ContextDocumentResponse, ContextDocumentType, } from "@/types/context"; interface UseContextDocumentsReturn { documents: ContextDocument[]; loading: boolean; error: string | null; createDocument: ( traceId: string, request: CreateContextRequest ) => Promise; updateDocument: ( traceId: string, contextId: string, updates: UpdateContextRequest ) => Promise; deleteDocument: (traceId: string, contextId: string) => Promise; uploadFile: ( traceId: string, file: File, title: string, documentType: ContextDocumentType ) => Promise; loadDocuments: (traceId: string) => Promise; refreshDocuments: (traceId: string) => Promise; } const API_BASE = "/api"; async function fetchApi( endpoint: string, options?: RequestInit ): Promise { const url = `${API_BASE}${endpoint}`; const response = await fetch(url, { headers: { "Content-Type": "application/json", ...options?.headers, }, ...options, }); if (!response.ok) { const errorText = await response.text(); throw new Error(`API Error: ${response.statusText} - ${errorText}`); } const data = await response.json(); return data; } export function useContextDocuments(): UseContextDocumentsReturn { const [documents, setDocuments] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const handleError = useCallback((err: any, defaultMessage: string) => { const message = err?.message || defaultMessage; setError(message); console.error(defaultMessage, err); return null; }, []); const loadDocuments = useCallback( async (traceId: string) => { setLoading(true); setError(null); try { const documents = await fetchApi( `/traces/${traceId}/context` ); setDocuments(documents || []); } catch (err) { handleError(err, "Failed to load context documents"); } finally { setLoading(false); } }, [handleError] ); const refreshDocuments = useCallback( async (traceId: string) => { await loadDocuments(traceId); }, [loadDocuments] ); const createDocument = useCallback( async ( traceId: string, request: CreateContextRequest ): Promise => { setLoading(true); setError(null); try { const response = await fetchApi( `/traces/${traceId}/context`, { method: "POST", body: JSON.stringify(request), } ); if (response.success && response.data) { setDocuments((prev) => [...prev, response.data!]); return response.data; } else { throw new Error(response.message || "Failed to create document"); } } catch (err) { return handleError(err, "Failed to create context document"); } finally { setLoading(false); } }, [handleError] ); const updateDocument = useCallback( async ( traceId: string, contextId: string, updates: UpdateContextRequest ): Promise => { setLoading(true); setError(null); try { const response = await fetchApi( `/traces/${traceId}/context/${contextId}`, { method: "PUT", body: JSON.stringify(updates), } ); if (response.success && response.data) { setDocuments((prev) => prev.map((doc) => (doc.id === contextId ? response.data! : doc)) ); return response.data; } else { throw new Error(response.message || "Failed to update document"); } } catch (err) { return handleError(err, "Failed to update context document"); } finally { setLoading(false); } }, [handleError] ); const deleteDocument = useCallback( async (traceId: string, contextId: string): Promise => { setLoading(true); setError(null); try { const response = await fetchApi( `/traces/${traceId}/context/${contextId}`, { method: "DELETE", } ); if (response.success) { setDocuments((prev) => prev.filter((doc) => doc.id !== contextId)); return true; } else { throw new Error(response.message || "Failed to delete document"); } } catch (err) { handleError(err, "Failed to delete context document"); return false; } finally { setLoading(false); } }, [handleError] ); const uploadFile = useCallback( async ( traceId: string, file: File, title: string, documentType: ContextDocumentType ): Promise => { setLoading(true); setError(null); try { const formData = new FormData(); formData.append("file", file); formData.append("title", title); formData.append("document_type", documentType); const response = await fetch( `${API_BASE}/traces/${traceId}/context/upload`, { method: "POST", body: formData, } ); if (!response.ok) { throw new Error(`Upload failed: ${response.statusText}`); } const result = (await response.json()) as ContextDocumentResponse; if (result.success && result.data) { setDocuments((prev) => [...prev, result.data!]); return result.data; } else { throw new Error(result.message || "Failed to upload file"); } } catch (err) { return handleError(err, "Failed to upload context file"); } finally { setLoading(false); } }, [handleError] ); return { documents, loading, error, createDocument, updateDocument, deleteDocument, uploadFile, loadDocuments, refreshDocuments, }; }