From 3ba71500bc2d60a00ca81b9439305029670f4d52 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Fri, 13 Feb 2026 06:55:21 -0800 Subject: Implement Frontend Feed Items View with tests --- frontend/src/components/FeedItems.tsx | 66 +++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 frontend/src/components/FeedItems.tsx (limited to 'frontend/src/components/FeedItems.tsx') diff --git a/frontend/src/components/FeedItems.tsx b/frontend/src/components/FeedItems.tsx new file mode 100644 index 0000000..048bed7 --- /dev/null +++ b/frontend/src/components/FeedItems.tsx @@ -0,0 +1,66 @@ +import { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import type { Item } from '../types'; +import './FeedItems.css'; + +export default function FeedItems() { + const { feedId } = useParams<{ feedId: string }>(); + const [items, setItems] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(''); + + useEffect(() => { + setLoading(true); + setError(''); + + const url = feedId + ? `/api/stream?feed_id=${feedId}` + : '/api/stream'; // Default or "all" view? For now let's assume we need a feedId or handle "all" logic later + + fetch(url) + .then((res) => { + if (!res.ok) { + throw new Error('Failed to fetch items'); + } + return res.json(); + }) + .then((data) => { + setItems(data); + setLoading(false); + }) + .catch((err) => { + setError(err.message); + setLoading(false); + }); + }, [feedId]); + + if (loading) return
Loading items...
; + if (error) return
Error: {error}
; + + return ( +
+

Items

+ {/* TODO: Add Feed Title here if possible, maybe pass from location state or fetch feed details */} + {items.length === 0 ? ( +

No items found.

+ ) : ( +
    + {items.map((item) => ( +
  • + + {item.title || '(No Title)'} + +
    + {new Date(item.publish_date).toLocaleDateString()} + {item.feed_title && - {item.feed_title}} +
    + {item.description && ( +
    + )} +
  • + ))} +
+ )} +
+ ); +} -- cgit v1.2.3