File size: 6,136 Bytes
f866820
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
100
101
102
103
104
105
106
107
import { useState, useEffect } from 'react';
import Sidebar from './components/Sidebar';
import QueryPanel from './components/QueryPanel';
import { getStatus } from './api/client';

export default function App() {
  const [status, setStatus] = useState(null);
  const [accessToken, setAccessToken] = useState(null);
  const [showPrivacyInfo, setShowPrivacyInfo] = useState(false);

  const fetchStatus = async () => {
    try {
      const data = await getStatus();
      setStatus(data);
    } catch (err) {
      console.error('Failed to fetch status:', err);
    }
  };

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

  return (
    <div className="flex h-screen bg-slate-900">
      <Sidebar onStatusChange={fetchStatus} onAccessTokenChange={setAccessToken} />
      <div className="flex-1 flex flex-col min-w-0">
        <header className="bg-gradient-to-r from-slate-800 to-slate-800/80 border-b border-slate-700 px-6 py-4 flex-shrink-0">
          <div className="flex items-center justify-between">
            {/* Left: App title */}
            <div className="flex items-center gap-3">
              <div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
                <svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                </svg>
              </div>
              <div>
                <h1 className="text-xl font-semibold text-slate-100">RAG Document Assistant</h1>
                <p className="text-xs text-slate-400">Search your documents with AI</p>
              </div>
            </div>

            {/* Right: Zero Storage Badge with Tooltip */}
            <div className="relative">
              <button
                type="button"
                onClick={() => setShowPrivacyInfo(!showPrivacyInfo)}
                className="flex items-center gap-1.5 bg-green-900/40 border border-green-700 rounded-md px-2.5 py-1.5 hover:bg-green-900/60 transition-colors cursor-pointer"
                aria-label="Learn about zero storage privacy"
              >
                <svg className="w-4 h-4 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
                </svg>
                <span className="text-sm font-medium text-green-400">Zero Storage</span>
                <svg className={`w-3 h-3 text-green-400 transition-transform ${showPrivacyInfo ? 'rotate-180' : ''}`} fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
                </svg>
              </button>

              {/* Privacy Info Dropdown */}
              {showPrivacyInfo && (
                <>
                  <div className="fixed inset-0 z-10" onClick={() => setShowPrivacyInfo(false)} />
                  <div className="absolute right-0 top-full mt-2 w-80 bg-slate-800 border border-slate-600 rounded-xl shadow-lg z-20 p-4">
                    <h3 className="font-semibold text-slate-100 mb-3 flex items-center gap-2">
                      <svg className="w-5 h-5 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
                      </svg>
                      How Your Privacy Is Protected
                    </h3>
                    <ul className="space-y-2.5 text-sm text-slate-300">
                      <li className="flex gap-2">
                        <span className="text-green-400 mt-0.5">&#10003;</span>
                        <span><strong className="text-slate-200">No server storage</strong> - Your documents are never stored on our servers</span>
                      </li>
                      <li className="flex gap-2">
                        <span className="text-green-400 mt-0.5">&#10003;</span>
                        <span><strong className="text-slate-200">Embeddings only</strong> - Text is converted to mathematical vectors, then immediately purged</span>
                      </li>
                      <li className="flex gap-2">
                        <span className="text-green-400 mt-0.5">&#10003;</span>
                        <span><strong className="text-slate-200">Query-time re-fetch</strong> - Text is retrieved fresh from YOUR Dropbox for each search</span>
                      </li>
                      <li className="flex gap-2">
                        <span className="text-green-400 mt-0.5">&#10003;</span>
                        <span><strong className="text-slate-200">LLM processing</strong> - Your text is sent to AI models for answer generation (not stored)</span>
                      </li>
                      <li className="flex gap-2">
                        <span className="text-green-400 mt-0.5">&#10003;</span>
                        <span><strong className="text-slate-200">You control access</strong> - Disconnect Dropbox anytime to revoke all access</span>
                      </li>
                    </ul>
                    <div className="mt-3 pt-3 border-t border-slate-700 text-xs text-slate-400">
                      Embeddings cannot be reversed to reconstruct your original text.
                    </div>
                  </div>
                </>
              )}
            </div>
          </div>
        </header>
        <QueryPanel accessToken={accessToken} />
      </div>
    </div>
  );
}