aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/src/components/Settings.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/components/Settings.tsx')
-rw-r--r--frontend/src/components/Settings.tsx64
1 files changed, 60 insertions, 4 deletions
diff --git a/frontend/src/components/Settings.tsx b/frontend/src/components/Settings.tsx
index 3f508e9..6b6dab1 100644
--- a/frontend/src/components/Settings.tsx
+++ b/frontend/src/components/Settings.tsx
@@ -9,6 +9,8 @@ export default function Settings() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
+ const [importFile, setImportFile] = useState<File | null>(null);
+
const fetchFeeds = () => {
setLoading(true);
apiFetch('/api/feed/')
@@ -30,8 +32,6 @@ export default function Settings() {
fetchFeeds();
}, []);
-
-
const handleAddFeed = (e: React.FormEvent) => {
e.preventDefault();
if (!newFeedUrl) return;
@@ -48,7 +48,7 @@ export default function Settings() {
})
.then(() => {
setNewFeedUrl('');
- fetchFeeds(); // Refresh list (or we could append if server returns full feed object)
+ fetchFeeds();
})
.catch((err) => {
setError(err.message);
@@ -74,6 +74,34 @@ export default function Settings() {
});
};
+ const handleImport = (e: React.FormEvent) => {
+ e.preventDefault();
+ if (!importFile) return;
+
+ setLoading(true);
+ const formData = new FormData();
+ formData.append('file', importFile);
+ formData.append('format', 'opml');
+
+ apiFetch('/api/import', {
+ method: 'POST',
+ body: formData,
+ })
+ .then((res) => {
+ if (!res.ok) throw new Error('Failed to import feeds');
+ return res.json();
+ })
+ .then(() => {
+ setImportFile(null);
+ fetchFeeds();
+ alert('Import successful!');
+ })
+ .catch((err) => {
+ setError(err.message);
+ setLoading(false);
+ });
+ };
+
return (
<div className="settings-page">
<h2>Settings</h2>
@@ -94,9 +122,37 @@ export default function Settings() {
Add Feed
</button>
</form>
- {error && <p className="error-message">{error}</p>}
</div>
+ <div className="import-export-section">
+ <div className="import-section">
+ <h3>Import Feeds (OPML)</h3>
+ <form onSubmit={handleImport} className="import-form">
+ <input
+ type="file"
+ accept=".opml,.xml,.txt"
+ onChange={(e) => setImportFile(e.target.files?.[0] || null)}
+ className="file-input"
+ disabled={loading}
+ />
+ <button type="submit" disabled={!importFile || loading}>
+ Import
+ </button>
+ </form>
+ </div>
+
+ <div className="export-section">
+ <h3>Export Feeds</h3>
+ <div className="export-buttons">
+ <a href="/api/export/opml" className="export-btn">OPML</a>
+ <a href="/api/export/text" className="export-btn">Text</a>
+ <a href="/api/export/json" className="export-btn">JSON</a>
+ </div>
+ </div>
+ </div>
+
+ {error && <p className="error-message">{error}</p>}
+
<div className="feed-list-section">
<h3>Manage Feeds</h3>
{loading && <p>Loading...</p>}