summaryrefslogtreecommitdiff
path: root/app/src/components/bookmark-fetcher.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/components/bookmark-fetcher.tsx')
-rw-r--r--app/src/components/bookmark-fetcher.tsx143
1 files changed, 143 insertions, 0 deletions
diff --git a/app/src/components/bookmark-fetcher.tsx b/app/src/components/bookmark-fetcher.tsx
new file mode 100644
index 0000000..6522310
--- /dev/null
+++ b/app/src/components/bookmark-fetcher.tsx
@@ -0,0 +1,143 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import { TwitterBookmark } from '../lib/bookmark-models';
+import { BookmarkStorageService } from '../lib/bookmark-storage';
+import { BookmarkList } from './bookmark-list';
+
+export function BookmarkFetcher() {
+ const [bookmarks, setBookmarks] = useState<TwitterBookmark[]>([]);
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState<string | null>(null);
+ const [username, setUsername] = useState('');
+ const [authToken, setAuthToken] = useState('');
+
+ // Load existing bookmarks on mount
+ useEffect(() => {
+ const existingBookmarks = BookmarkStorageService.getBookmarks();
+ setBookmarks(existingBookmarks);
+ }, []);
+
+ const handleFetchBookmarks = async () => {
+ if (!username || !authToken) {
+ setError('Please enter your Twitter username and auth token');
+ return;
+ }
+
+ setLoading(true);
+ setError(null);
+
+ try {
+ // Simple fetch to our API endpoint
+ const response = await fetch('/api/sync-bookmarks', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ username, authToken }),
+ });
+
+ const result = await response.json();
+
+ if (!result.success) {
+ throw new Error(result.error || 'Failed to fetch bookmarks');
+ }
+
+ // Load the newly saved bookmarks
+ const updatedBookmarks = BookmarkStorageService.getBookmarks();
+ setBookmarks(updatedBookmarks);
+
+ } catch (err) {
+ setError(err instanceof Error ? err.message : 'Failed to fetch bookmarks');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleClearBookmarks = () => {
+ BookmarkStorageService.clearAll();
+ setBookmarks([]);
+ };
+
+ return (
+ <div className="space-y-6">
+ {/* Input fields */}
+ <div className="bg-white border border-gray-200 rounded-lg p-6">
+ <h2 className="text-xl font-semibold mb-4">Twitter Credentials</h2>
+
+ <div className="space-y-4">
+ <div>
+ <label htmlFor="username" className="block text-sm font-medium text-gray-700 mb-1">
+ Twitter Username
+ </label>
+ <input
+ id="username"
+ type="text"
+ value={username}
+ onChange={(e) => setUsername(e.target.value)}
+ placeholder="your_twitter_username"
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
+ />
+ </div>
+
+ <div>
+ <label htmlFor="authToken" className="block text-sm font-medium text-gray-700 mb-1">
+ Auth Token
+ </label>
+ <input
+ id="authToken"
+ type="password"
+ value={authToken}
+ onChange={(e) => setAuthToken(e.target.value)}
+ placeholder="your_auth_token"
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
+ />
+ </div>
+ </div>
+ </div>
+
+ {/* Action buttons */}
+ <div className="flex gap-4">
+ <button
+ onClick={handleFetchBookmarks}
+ disabled={loading}
+ className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-blue-300 disabled:cursor-not-allowed font-medium"
+ >
+ {loading ? (
+ <>
+ <svg className="animate-spin -ml-1 mr-3 h-5 w-5 text-white inline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
+ <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
+ </svg>
+ Fetching...
+ </>
+ ) : (
+ 'Fetch Twitter Bookmarks'
+ )}
+ </button>
+
+ {bookmarks.length > 0 && (
+ <button
+ onClick={handleClearBookmarks}
+ className="px-6 py-3 bg-red-600 text-white rounded-lg hover:bg-red-700 font-medium"
+ >
+ Clear All
+ </button>
+ )}
+ </div>
+
+ {/* Error message */}
+ {error && (
+ <div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-lg">
+ {error}
+ </div>
+ )}
+
+ {/* Bookmark list */}
+ <div className="bg-white border border-gray-200 rounded-lg p-6">
+ <h2 className="text-xl font-semibold mb-4">Your Bookmarks</h2>
+ <BookmarkList bookmarks={bookmarks} />
+ </div>
+ </div>
+ );
+} \ No newline at end of file