gni commited on
Commit
945586b
·
1 Parent(s): b6037e3

feat: add frontend error notification for rate limiting

Browse files
Files changed (1) hide show
  1. ui/src/App.tsx +24 -1
ui/src/App.tsx CHANGED
@@ -33,6 +33,7 @@ function App() {
33
  const [language, setLanguage] = useState('auto');
34
  const [theme, setTheme] = useState<Theme>(() => (localStorage.getItem('pg-theme') as Theme) || 'premium');
35
  const [result, setResult] = useState<RedactResponse | null>(null);
 
36
  const [loading, setLoading] = useState(false);
37
  const [apiStatus, setApiStatus] = useState<'checking' | 'online' | 'offline'>('online');
38
  const [copied, setCopied] = useState(false);
@@ -66,10 +67,16 @@ function App() {
66
  const handleRedact = async () => {
67
  if (!text.trim()) return;
68
  setLoading(true);
 
69
  try {
70
  const response = await axios.post(`${API_URL}/api/redact`, { text, language });
71
  setResult(response.data);
72
- } catch (err: any) { console.error(err); }
 
 
 
 
 
73
  finally { setTimeout(() => setLoading(false), 400); }
74
  };
75
 
@@ -192,6 +199,22 @@ function App() {
192
 
193
  <div className="flex-grow md:flex-grow relative overflow-hidden bg-inherit h-[500px] md:h-auto md:min-h-0">
194
  {loading && <div className="loading-progress"><div className="loading-progress-bar" /></div>}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  <textarea
196
  className={`w-full h-full p-4 sm:p-10 bg-transparent border-none outline-none text-[15px] sm:text-[16px] leading-[1.8] resize-none font-sans custom-scrollbar ${themeClasses.input}`}
197
  placeholder="Enter your document content here..."
 
33
  const [language, setLanguage] = useState('auto');
34
  const [theme, setTheme] = useState<Theme>(() => (localStorage.getItem('pg-theme') as Theme) || 'premium');
35
  const [result, setResult] = useState<RedactResponse | null>(null);
36
+ const [error, setError] = useState<string | null>(null);
37
  const [loading, setLoading] = useState(false);
38
  const [apiStatus, setApiStatus] = useState<'checking' | 'online' | 'offline'>('online');
39
  const [copied, setCopied] = useState(false);
 
67
  const handleRedact = async () => {
68
  if (!text.trim()) return;
69
  setLoading(true);
70
+ setError(null);
71
  try {
72
  const response = await axios.post(`${API_URL}/api/redact`, { text, language });
73
  setResult(response.data);
74
+ } catch (err: any) {
75
+ console.error(err);
76
+ const msg = err.response?.data?.detail || 'An unexpected error occurred.';
77
+ setError(typeof msg === 'string' ? msg : 'Analysis failed. Please try again.');
78
+ setTimeout(() => setError(null), 6000);
79
+ }
80
  finally { setTimeout(() => setLoading(false), 400); }
81
  };
82
 
 
199
 
200
  <div className="flex-grow md:flex-grow relative overflow-hidden bg-inherit h-[500px] md:h-auto md:min-h-0">
201
  {loading && <div className="loading-progress"><div className="loading-progress-bar" /></div>}
202
+
203
+ {/* Error Alert */}
204
+ {error && (
205
+ <div className="absolute top-4 left-4 right-4 z-[60] animate-in slide-in-from-top-4 duration-300">
206
+ <div className="bg-rose-500 text-white px-4 py-3 rounded-xl shadow-2xl flex items-center justify-between gap-3 border border-rose-400">
207
+ <div className="flex items-center gap-3">
208
+ <Shield className="w-5 h-5 flex-none" />
209
+ <p className="text-[11px] sm:text-xs font-bold leading-tight uppercase tracking-wider">{error}</p>
210
+ </div>
211
+ <button onClick={() => setError(null)} className="p-1 hover:bg-white/20 rounded-lg transition-colors">
212
+ <Trash2 className="w-4 h-4" />
213
+ </button>
214
+ </div>
215
+ </div>
216
+ )}
217
+
218
  <textarea
219
  className={`w-full h-full p-4 sm:p-10 bg-transparent border-none outline-none text-[15px] sm:text-[16px] leading-[1.8] resize-none font-sans custom-scrollbar ${themeClasses.input}`}
220
  placeholder="Enter your document content here..."