File size: 3,185 Bytes
32c4f08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9330b9f
32c4f08
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { useState, useEffect } from 'react';
import FileUpload from './components/FileUpload';
import ChatWindow from './components/ChatWindow';
import DocumentList from './components/DocumentList';
import { listDocuments } from './services/api';

export default function App() {
  const [documents, setDocuments] = useState([]);
  const [isLoadingDocs, setIsLoadingDocs] = useState(true);
  const [sidebarOpen, setSidebarOpen] = useState(true);

  const fetchDocuments = async () => {
    try {
      setIsLoadingDocs(true);
      const result = await listDocuments();
      setDocuments(result.documents || []);
    } catch (err) {
      console.error('Failed to fetch documents:', err);
    } finally {
      setIsLoadingDocs(false);
    }
  };

  useEffect(() => {
    fetchDocuments();
  }, []);

  const handleUploadSuccess = (doc) => {
    setDocuments((prev) => [...prev, doc]);
  };

  const handleDocumentDeleted = (docId) => {
    setDocuments((prev) => prev.filter((d) => d.id !== docId));
  };

  return (
    <div className="app">
      {/* Sidebar */}
      <aside className={`sidebar ${sidebarOpen ? 'open' : 'closed'}`}>
        <div className="sidebar-header">
          <div className="logo">
            <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
              <path d="M12 2a4 4 0 0 1 4 4v2a4 4 0 0 1-8 0V6a4 4 0 0 1 4-4z" />
              <path d="M6 10a6 6 0 0 0 12 0" />
              <rect x="9" y="14" width="6" height="4" rx="1" />
              <path d="M8 18h8v2a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-2z" />
            </svg>
            <span>RAG Assistant</span>
          </div>
          <button
            className="sidebar-toggle"
            onClick={() => setSidebarOpen(!sidebarOpen)}
          >
            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              {sidebarOpen ? (
                <path d="M15 18l-6-6 6-6" />
              ) : (
                <path d="M9 18l6-6-6-6" />
              )}
            </svg>
          </button>
        </div>

        <div className="sidebar-content">
          <FileUpload onUploadSuccess={handleUploadSuccess} documentCount={documents.length} />
          <DocumentList
            documents={documents}
            onDocumentDeleted={handleDocumentDeleted}
            isLoading={isLoadingDocs}
          />
        </div>

        <div className="sidebar-footer">
          <p>Powered by GPT-4o-mini</p>
        </div>
      </aside>

      {/* Mobile sidebar toggle */}
      {!sidebarOpen && (
        <button
          className="mobile-sidebar-toggle"
          onClick={() => setSidebarOpen(true)}
        >
          <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <line x1="3" y1="12" x2="21" y2="12" />
            <line x1="3" y1="6" x2="21" y2="6" />
            <line x1="3" y1="18" x2="21" y2="18" />
          </svg>
        </button>
      )}

      {/* Main Chat Area */}
      <main className="main-content">
        <ChatWindow hasDocuments={documents.length > 0} />
      </main>
    </div>
  );
}