Skip to main content
Glama

MCP-RSS-Crawler

by mshk
Sidebar.tsx4.89 kB
import { useEffect, useState } from 'react'; import Link from 'next/link'; import { Feed } from '@/lib/db'; interface SidebarProps { selectedCategory?: string; selectedFeed?: string; } export default function Sidebar({ selectedCategory, selectedFeed }: SidebarProps) { const [categories, setCategories] = useState<string[]>([]); const [feeds, setFeeds] = useState<Feed[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState<string | null>(null); // Fetch categories and feeds useEffect(() => { const fetchData = async () => { try { setLoading(true); // Fetch categories const categoriesResponse = await fetch('/api/categories'); if (!categoriesResponse.ok) { throw new Error('Failed to fetch categories'); } const categoriesData = await categoriesResponse.json(); setCategories(categoriesData); // Fetch feeds const feedsResponse = await fetch('/api/feeds'); if (!feedsResponse.ok) { throw new Error('Failed to fetch feeds'); } const feedsData = await feedsResponse.json(); setFeeds(feedsData); setLoading(false); } catch (err) { setError(err instanceof Error ? err.message : 'An error occurred'); setLoading(false); } }; fetchData(); }, []); // Group feeds by category const feedsByCategory: Record<string, Feed[]> = {}; const uncategorizedFeeds: Feed[] = []; feeds.forEach(feed => { if (feed.category) { if (!feedsByCategory[feed.category]) { feedsByCategory[feed.category] = []; } feedsByCategory[feed.category].push(feed); } else { uncategorizedFeeds.push(feed); } }); if (loading) { return ( <div className="w-64 bg-gray-100 p-4 h-screen"> <h2 className="text-xl font-bold mb-4">RSS Feeds</h2> <div className="animate-pulse"> <div className="h-4 bg-gray-300 rounded mb-2"></div> <div className="h-4 bg-gray-300 rounded mb-2"></div> <div className="h-4 bg-gray-300 rounded mb-2"></div> </div> </div> ); } if (error) { return ( <div className="w-64 bg-gray-100 p-4 h-screen"> <h2 className="text-xl font-bold mb-4">RSS Feeds</h2> <div className="text-red-500">Error: {error}</div> </div> ); } return ( <div className="w-64 bg-gray-100 p-4 h-screen flex flex-col"> <h2 className="text-xl font-bold mb-4">RSS Feeds</h2> <div className="mb-4"> <Link href="/" className={`block p-2 rounded ${!selectedCategory && !selectedFeed ? 'bg-blue-500 text-white' : 'hover:bg-gray-200'}`} > All Recent Items </Link> </div> <div className="mb-4"> <h3 className="font-semibold mb-2">Categories</h3> <ul> {categories.map(category => ( <li key={category}> <Link href={`/category/${encodeURIComponent(category)}`} className={`block p-2 rounded ${selectedCategory === category ? 'bg-blue-500 text-white' : 'hover:bg-gray-200'}`} > {category} </Link> </li> ))} </ul> </div> <div className="flex-1 overflow-y-auto"> <h3 className="font-semibold mb-2">All Feeds</h3> {Object.entries(feedsByCategory).map(([category, categoryFeeds]) => ( <div key={category} className="mb-4"> <h4 className="text-sm font-medium text-gray-600 mb-1">{category}</h4> <ul className="pl-2"> {categoryFeeds.map(feed => ( <li key={feed.id}> <Link href={`/feed/${encodeURIComponent(feed.id)}`} className={`block p-2 rounded ${selectedFeed === feed.id ? 'bg-blue-500 text-white' : 'hover:bg-gray-200'}`} > {feed.name} </Link> </li> ))} </ul> </div> ))} {uncategorizedFeeds.length > 0 && ( <div className="mb-4"> <h4 className="text-sm font-medium text-gray-600 mb-1">Uncategorized</h4> <ul className="pl-2"> {uncategorizedFeeds.map(feed => ( <li key={feed.id}> <Link href={`/feed/${encodeURIComponent(feed.id)}`} className={`block p-2 rounded ${selectedFeed === feed.id ? 'bg-blue-500 text-white' : 'hover:bg-gray-200'}`} > {feed.name} </Link> </li> ))} </ul> </div> )} </div> </div> ); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mshk/mcp-rss-crawler'

If you have feedback or need assistance with the MCP directory API, please join our Discord server