diff --git a/app/api/rss/route.ts b/app/api/rss/route.ts index 5f28f53..dc2051c 100644 --- a/app/api/rss/route.ts +++ b/app/api/rss/route.ts @@ -8,6 +8,7 @@ export async function GET(req: NextRequest) { const q = searchParams.get('q'); const feedId = searchParams.get('feed_id'); const bookmarked = searchParams.get('bookmarked'); + const since = searchParams.get('since'); const limit = parseInt(searchParams.get('limit') || '50', 10); const offset = parseInt(searchParams.get('offset') || '0', 10); @@ -27,6 +28,19 @@ export async function GET(req: NextRequest) { if (bookmarked === '1') { conditions.push('i.bookmarked = 1'); } + if (since) { + const sinceMap: Record = { + '1h': '-1 hours', + '24h': '-24 hours', + '7d': '-7 days', + '30d': '-30 days', + }; + const modifier = sinceMap[since]; + if (modifier) { + conditions.push("i.pub_date >= datetime('now', ?)"); + params.push(modifier); + } + } const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''; diff --git a/components/widgets/NewsFeed.tsx b/components/widgets/NewsFeed.tsx index 4f39ab5..d243a53 100644 --- a/components/widgets/NewsFeed.tsx +++ b/components/widgets/NewsFeed.tsx @@ -150,6 +150,51 @@ function FeedFilterPills({ ); } +type TimeFilter = '1h' | '24h' | '7d' | '30d'; + +const TIME_FILTER_OPTIONS: { value: TimeFilter; label: string }[] = [ + { value: '1h', label: '1h' }, + { value: '24h', label: '24h' }, + { value: '7d', label: '7d' }, + { value: '30d', label: '30d' }, +]; + +function TimeFilterPills({ + active, + onSelect, +}: { + active: TimeFilter | null; + onSelect: (v: TimeFilter | null) => void; +}) { + return ( +
+ + {TIME_FILTER_OPTIONS.map((opt) => ( + + ))} +
+ ); +} + function AddFeedForm({ onAdded }: { onAdded: () => void }) { const [url, setUrl] = useState(''); const [submitting, setSubmitting] = useState(false); @@ -332,6 +377,7 @@ export function NewsFeed() { const [feeds, setFeeds] = useState([]); const [searchQuery, setSearchQuery] = useState(''); const [activeFeedId, setActiveFeedId] = useState(null); + const [timeFilter, setTimeFilter] = useState(null); const [showBookmarked, setShowBookmarked] = useState(false); const [showFeedManager, setShowFeedManager] = useState(false); const [loading, setLoading] = useState(true); @@ -354,6 +400,7 @@ export function NewsFeed() { if (searchQuery) params.set('q', searchQuery); if (!opts?.resetFeedFilter && activeFeedId !== null) params.set('feed_id', String(activeFeedId)); if (showBookmarked) params.set('bookmarked', '1'); + if (timeFilter) params.set('since', timeFilter); params.set('limit', '50'); const res = await fetch(`/api/rss?${params}`); @@ -373,7 +420,7 @@ export function NewsFeed() { } finally { setLoading(false); } - }, [searchQuery, activeFeedId, showBookmarked]); + }, [searchQuery, activeFeedId, showBookmarked, timeFilter]); // Initial load + refresh useEffect(() => { @@ -469,6 +516,13 @@ export function NewsFeed() { )} + {/* Time filter pills */} + {hasFeeds && ( +
+ +
+ )} + {/* Feed manager (collapsible) */} {showFeedManager && (