import axios from "axios"; import React, { useCallback, useEffect, useState } from "react"; import "react-tag-autocomplete/example/src/styles.css"; // Ensure styles are loaded import DocumentsToProcess from "./components/DocumentsToProcess"; import NoDocuments from "./components/NoDocuments"; import SuccessModal from "./components/SuccessModal"; import SuggestionsReview from "./components/SuggestionsReview"; export interface Document { id: number; title: string; content: string; tags: string[]; } export interface GenerateSuggestionsRequest { documents: Document[]; generate_titles?: boolean; generate_tags?: boolean; } export interface DocumentSuggestion { id: number; original_document: Document; suggested_title?: string; suggested_tags?: string[]; } export interface TagOption { id: string; name: string; } const DocumentProcessor: React.FC = () => { const [documents, setDocuments] = useState([]); const [suggestions, setSuggestions] = useState([]); const [availableTags, setAvailableTags] = useState([]); const [loading, setLoading] = useState(true); const [processing, setProcessing] = useState(false); const [updating, setUpdating] = useState(false); const [isSuccessModalOpen, setIsSuccessModalOpen] = useState(false); const [filterTag, setFilterTag] = useState(null); const [generateTitles, setGenerateTitles] = useState(true); const [generateTags, setGenerateTags] = useState(true); const [error, setError] = useState(null); // Custom hook to fetch initial data const fetchInitialData = useCallback(async () => { try { const [filterTagRes, documentsRes, tagsRes] = await Promise.all([ axios.get<{ tag: string }>("/api/filter-tag"), axios.get("/api/documents"), axios.get>("/api/tags"), ]); setFilterTag(filterTagRes.data.tag); setDocuments(documentsRes.data); const tags = Object.keys(tagsRes.data).map((tag) => ({ id: tag, name: tag, })); setAvailableTags(tags); } catch (err) { console.error("Error fetching initial data:", err); setError("Failed to fetch initial data."); } finally { setLoading(false); } }, []); useEffect(() => { fetchInitialData(); }, [fetchInitialData]); const handleProcessDocuments = async () => { setProcessing(true); setError(null); try { const requestPayload: GenerateSuggestionsRequest = { documents, generate_titles: generateTitles, generate_tags: generateTags, }; const { data } = await axios.post( "/api/generate-suggestions", requestPayload ); setSuggestions(data); } catch (err) { console.error("Error generating suggestions:", err); setError("Failed to generate suggestions."); } finally { setProcessing(false); } }; const handleUpdateDocuments = async () => { setUpdating(true); setError(null); try { await axios.patch("/api/update-documents", suggestions); setIsSuccessModalOpen(true); setSuggestions([]); } catch (err) { console.error("Error updating documents:", err); setError("Failed to update documents."); } finally { setUpdating(false); } }; const handleTagAddition = (docId: number, tag: TagOption) => { setSuggestions((prevSuggestions) => prevSuggestions.map((doc) => doc.id === docId ? { ...doc, suggested_tags: [...(doc.suggested_tags || []), tag.name], } : doc ) ); }; const handleTagDeletion = (docId: number, index: number) => { setSuggestions((prevSuggestions) => prevSuggestions.map((doc) => doc.id === docId ? { ...doc, suggested_tags: doc.suggested_tags?.filter( (_, i) => i !== index ), } : doc ) ); }; const handleTitleChange = (docId: number, title: string) => { setSuggestions((prevSuggestions) => prevSuggestions.map((doc) => doc.id === docId ? { ...doc, suggested_title: title } : doc ) ); }; const resetSuggestions = () => { setSuggestions([]); }; const reloadDocuments = async () => { setLoading(true); setError(null); try { const { data } = await axios.get("/api/documents"); setDocuments(data); } catch (err) { console.error("Error reloading documents:", err); setError("Failed to reload documents."); } finally { setLoading(false); } }; useEffect(() => { if (documents.length === 0) { const interval = setInterval(async () => { setError(null); try { const { data } = await axios.get("/api/documents"); setDocuments(data); } catch (err) { console.error("Error reloading documents:", err); setError("Failed to reload documents."); } }, 500); return () => clearInterval(interval); } }, [documents]); if (loading) { return (
Loading documents...
); } return (

Paperless GPT

{error && (
{error}
)} {documents.length === 0 ? ( ) : suggestions.length === 0 ? ( ) : ( )} { setIsSuccessModalOpen(false); reloadDocuments(); }} />
); }; export default DocumentProcessor;