Spaces:
Running
Running
| /** | |
| * 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<ContextDocument | null>; | |
| updateDocument: ( | |
| traceId: string, | |
| contextId: string, | |
| updates: UpdateContextRequest | |
| ) => Promise<ContextDocument | null>; | |
| deleteDocument: (traceId: string, contextId: string) => Promise<boolean>; | |
| uploadFile: ( | |
| traceId: string, | |
| file: File, | |
| title: string, | |
| documentType: ContextDocumentType | |
| ) => Promise<ContextDocument | null>; | |
| loadDocuments: (traceId: string) => Promise<void>; | |
| refreshDocuments: (traceId: string) => Promise<void>; | |
| } | |
| const API_BASE = "/api"; | |
| async function fetchApi<T>( | |
| endpoint: string, | |
| options?: RequestInit | |
| ): Promise<T> { | |
| 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<ContextDocument[]>([]); | |
| const [loading, setLoading] = useState(false); | |
| const [error, setError] = useState<string | null>(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<ContextDocument[]>( | |
| `/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<ContextDocument | null> => { | |
| setLoading(true); | |
| setError(null); | |
| try { | |
| const response = await fetchApi<ContextDocumentResponse>( | |
| `/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<ContextDocument | null> => { | |
| setLoading(true); | |
| setError(null); | |
| try { | |
| const response = await fetchApi<ContextDocumentResponse>( | |
| `/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<boolean> => { | |
| setLoading(true); | |
| setError(null); | |
| try { | |
| const response = await fetchApi<ContextDocumentResponse>( | |
| `/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<ContextDocument | null> => { | |
| 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, | |
| }; | |
| } | |