From e3c379d069ffa9661561d25cdbf2f5894a2f8ee8 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Sat, 14 Feb 2026 08:58:38 -0800 Subject: Refactor: project structure, implement dependency injection, and align v2 UI with v1 --- frontend/src/components/Settings.tsx | 214 ++++++++++++++++++----------------- 1 file changed, 108 insertions(+), 106 deletions(-) (limited to 'frontend/src/components/Settings.tsx') diff --git a/frontend/src/components/Settings.tsx b/frontend/src/components/Settings.tsx index def8ffe..b4f6a3b 100644 --- a/frontend/src/components/Settings.tsx +++ b/frontend/src/components/Settings.tsx @@ -3,119 +3,121 @@ import type { Feed } from '../types'; import './Settings.css'; export default function Settings() { - const [feeds, setFeeds] = useState([]); - const [newFeedUrl, setNewFeedUrl] = useState(''); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(null); + const [feeds, setFeeds] = useState([]); + const [newFeedUrl, setNewFeedUrl] = useState(''); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); - useEffect(() => { - fetchFeeds(); - }, []); + const fetchFeeds = () => { + setLoading(true); + fetch('/api/feed/') + .then((res) => { + if (!res.ok) throw new Error('Failed to fetch feeds'); + return res.json(); + }) + .then((data) => { + setFeeds(data); + setLoading(false); + }) + .catch((err) => { + setError(err.message); + setLoading(false); + }); + }; - const fetchFeeds = () => { - setLoading(true); - fetch('/api/feed/') - .then((res) => { - if (!res.ok) throw new Error('Failed to fetch feeds'); - return res.json(); - }) - .then((data) => { - setFeeds(data); - setLoading(false); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }; + useEffect(() => { + fetchFeeds(); + }, []); - const handleAddFeed = (e: React.FormEvent) => { - e.preventDefault(); - if (!newFeedUrl) return; - setLoading(true); - fetch('/api/feed/', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ url: newFeedUrl }), - }) - .then((res) => { - if (!res.ok) throw new Error('Failed to add feed'); - return res.json(); - }) - .then(() => { - setNewFeedUrl(''); - fetchFeeds(); // Refresh list (or we could append if server returns full feed object) - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }; - const handleDeleteFeed = (id: number) => { - if (!globalThis.confirm('Are you sure you want to delete this feed?')) return; + const handleAddFeed = (e: React.FormEvent) => { + e.preventDefault(); + if (!newFeedUrl) return; - setLoading(true); - fetch(`/api/feed/${id}`, { - method: 'DELETE', - }) - .then((res) => { - if (!res.ok) throw new Error('Failed to delete feed'); - setFeeds(feeds.filter((f) => f._id !== id)); - setLoading(false); - }) - .catch((err) => { - setError(err.message); - setLoading(false); - }); - }; + setLoading(true); + fetch('/api/feed/', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ url: newFeedUrl }), + }) + .then((res) => { + if (!res.ok) throw new Error('Failed to add feed'); + return res.json(); + }) + .then(() => { + setNewFeedUrl(''); + fetchFeeds(); // Refresh list (or we could append if server returns full feed object) + }) + .catch((err) => { + setError(err.message); + setLoading(false); + }); + }; - return ( -
-

Settings

+ const handleDeleteFeed = (id: number) => { + if (!globalThis.confirm('Are you sure you want to delete this feed?')) return; -
-

Add New Feed

-
- setNewFeedUrl(e.target.value)} - placeholder="https://example.com/feed.xml" - required - className="feed-input" - disabled={loading} - /> - -
- {error &&

{error}

} -
+ setLoading(true); + fetch(`/api/feed/${id}`, { + method: 'DELETE', + }) + .then((res) => { + if (!res.ok) throw new Error('Failed to delete feed'); + setFeeds(feeds.filter((f) => f._id !== id)); + setLoading(false); + }) + .catch((err) => { + setError(err.message); + setLoading(false); + }); + }; -
-

Manage Feeds

- {loading &&

Loading...

} -
    - {feeds.map((feed) => ( -
  • -
    - {feed.title || '(No Title)'} - {feed.url} -
    - -
  • - ))} -
-
-
- ); + return ( +
+

Settings

+ +
+

Add New Feed

+
+ setNewFeedUrl(e.target.value)} + placeholder="https://example.com/feed.xml" + required + className="feed-input" + disabled={loading} + /> + +
+ {error &&

{error}

} +
+ +
+

Manage Feeds

+ {loading &&

Loading...

} +
    + {feeds.map((feed) => ( +
  • +
    + {feed.title || '(No Title)'} + {feed.url} +
    + +
  • + ))} +
+
+
+ ); } -- cgit v1.2.3