FeedItemList.tsx•5.73 kB
import { useEffect, useState } from 'react';
import { FeedItem } from '@/lib/db';
import FeedItemCard from './FeedItemCard';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
interface FeedItemListProps {
  feedId?: string;
  category?: string;
  searchQuery?: string;
}
export default function FeedItemList({ feedId, category, searchQuery }: FeedItemListProps) {
  const router = useRouter();
  const [items, setItems] = useState<FeedItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [hasArticles, setHasArticles] = useState(false);
  const [fetchingFeeds, setFetchingFeeds] = useState(false);
  const fetchFeeds = async () => {
    try {
      setFetchingFeeds(true);
      const response = await fetch('/api/feeds/fetch', {
        method: 'POST',
      });
      
      if (!response.ok) {
        throw new Error('Failed to fetch feeds');
      }
      
      const data = await response.json();
      console.log('Fetch feeds response:', data);
      
      // Refresh the page to show the new feeds
      router.refresh();
      
      // Reload the items
      fetchItems();
    } catch (err) {
      console.error('Error fetching feeds:', err);
      setError(err instanceof Error ? err.message : 'Failed to fetch feeds');
    } finally {
      setFetchingFeeds(false);
    }
  };
  const fetchItems = async () => {
    try {
      setLoading(true);
      
      // Build the query URL based on the props
      let url = '/api/items';
      const params = new URLSearchParams();
      
      if (feedId) {
        params.append('feedId', feedId);
      } else if (category) {
        params.append('category', category);
      } else if (searchQuery) {
        params.append('query', searchQuery);
      }
      
      if (params.toString()) {
        url += `?${params.toString()}`;
      }
      
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error('Failed to fetch items');
      }
      
      const data = await response.json();
      setItems(data);
      
      // Check if articles are available in the database
      try {
        const articleCheckResponse = await fetch('/api/articles/check');
        if (articleCheckResponse.ok) {
          const checkData = await articleCheckResponse.json();
          setHasArticles(checkData.hasArticles);
        }
      } catch (err) {
        console.error('Error checking for articles:', err);
        setHasArticles(false);
      }
      
      setLoading(false);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'An error occurred');
      setLoading(false);
    }
  };
  
  useEffect(() => {
    fetchItems();
  }, [feedId, category, searchQuery]);
  if (loading) {
    return (
      <div className="p-4">
        <div className="animate-pulse space-y-4">
          {[...Array(5)].map((_, i) => (
            <div key={i} className="border rounded-lg p-4">
              <div className="h-5 bg-gray-300 rounded w-3/4 mb-2"></div>
              <div className="h-4 bg-gray-300 rounded w-1/4 mb-3"></div>
              <div className="h-4 bg-gray-300 rounded w-full mb-2"></div>
              <div className="h-4 bg-gray-300 rounded w-full mb-2"></div>
              <div className="h-4 bg-gray-300 rounded w-2/3"></div>
            </div>
          ))}
        </div>
      </div>
    );
  }
  if (error) {
    return (
      <div className="p-4">
        <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
          <p>Error: {error}</p>
        </div>
      </div>
    );
  }
  if (items.length === 0) {
    return (
      <div className="p-4">
        <div className="flex justify-between items-center mb-4">
          <h2 className="text-xl font-bold flex items-center">
            {feedId ? 'Feed Items' : category ? `Items in ${category}` : searchQuery ? `Search Results for "${searchQuery}"` : 'Recent Items'}
          </h2>
          <button
            onClick={fetchFeeds}
            disabled={fetchingFeeds}
            className={`px-4 py-2 rounded text-white ${fetchingFeeds ? 'bg-gray-400' : 'bg-blue-500 hover:bg-blue-600'}`}
          >
            {fetchingFeeds ? 'Fetching...' : 'Fetch Feeds'}
          </button>
        </div>
        <div className="bg-yellow-100 border border-yellow-400 text-yellow-700 px-4 py-3 rounded">
          <p>No items found. Click the "Fetch Feeds" button to retrieve RSS feeds.</p>
        </div>
      </div>
    );
  }
  return (
    <div className="p-4">
      <div className="mb-4">
        <div className="flex justify-between items-center">
          <h2 className="text-xl font-bold flex items-center">
            {feedId ? 'Feed Items' : category ? `Items in ${category}` : searchQuery ? `Search Results for "${searchQuery}"` : 'Recent Items'}
            {hasArticles && (
              <Image 
                src="/file.svg" 
                alt="Articles available" 
                width={16} 
                height={16} 
                className="ml-2" 
                title="Articles available"
              />
            )}
          </h2>
          <button
            onClick={fetchFeeds}
            disabled={fetchingFeeds}
            className={`px-4 py-2 rounded text-white ${fetchingFeeds ? 'bg-gray-400' : 'bg-blue-500 hover:bg-blue-600'}`}
          >
            {fetchingFeeds ? 'Fetching...' : 'Fetch Feeds'}
          </button>
        </div>
        <p className="text-gray-600">{items.length} items found</p>
      </div>
      
      <div>
        {items.map(item => (
          <FeedItemCard key={item.id} item={item} />
        ))}
      </div>
    </div>
  );
}