瀏覽代碼

feat: Display unread articles count in title

Adds the number of unread articles to the page title, enclosed in parentheses.
gpt-engineer-app[bot] 5 月之前
父節點
當前提交
42143e7ff9
共有 1 個文件被更改,包括 106 次插入27 次删除
  1. 106 27
      src/pages/Index.tsx

+ 106 - 27
src/pages/Index.tsx

@@ -1,4 +1,4 @@
-import { useState, useMemo } from 'react';
+import { useState, useMemo, useEffect } from 'react';
 import { categories } from '@/data/mockNews';
 import { useRealArticles } from '@/hooks/useRealArticles';
 import { useAuth } from '@/hooks/useAuth';
@@ -14,10 +14,9 @@ import { Card, CardContent } from '@/components/ui/card';
 import { RefreshCw, Filter, User, Rss, Plus } from 'lucide-react';
 import { toast } from 'sonner';
 import { Link } from 'react-router-dom';
+
 const Index = () => {
-  const {
-    user
-  } = useAuth();
+  const { user } = useAuth();
   const {
     articles,
     loading,
@@ -32,7 +31,9 @@ const Index = () => {
   const [isAddFeedModalOpen, setIsAddFeedModalOpen] = useState(false);
   const [selectedArticle, setSelectedArticle] = useState<NewsItem | null>(null);
   const [isArticleModalOpen, setIsArticleModalOpen] = useState(false);
+
   console.log('🏠 Index page - Articles count:', articles.length, 'Loading:', loading, 'User:', !!user);
+
   const filteredNews = useMemo(() => {
     let filtered = articles;
     if (selectedCategory) {
@@ -42,7 +43,11 @@ const Index = () => {
       }
     }
     if (searchQuery) {
-      filtered = filtered.filter(item => item.title.toLowerCase().includes(searchQuery.toLowerCase()) || item.description.toLowerCase().includes(searchQuery.toLowerCase()) || item.source.toLowerCase().includes(searchQuery.toLowerCase()));
+      filtered = filtered.filter(item => 
+        item.title.toLowerCase().includes(searchQuery.toLowerCase()) || 
+        item.description.toLowerCase().includes(searchQuery.toLowerCase()) || 
+        item.source.toLowerCase().includes(searchQuery.toLowerCase())
+      );
     }
     return filtered.sort((a, b) => {
       if (a.isPinned && !b.isPinned) return -1;
@@ -50,42 +55,67 @@ const Index = () => {
       return new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime();
     });
   }, [articles, selectedCategory, searchQuery]);
+
   const pinnedCount = articles.filter(item => item.isPinned).length;
   const unreadCount = articles.length; // All displayed articles are unread now
 
+  // Update document title with unread count
+  useEffect(() => {
+    const baseTitle = 'Feeds.Duhaz.fr';
+    if (unreadCount > 0) {
+      document.title = `(${unreadCount}) ${baseTitle}`;
+    } else {
+      document.title = baseTitle;
+    }
+  }, [unreadCount]);
+
   const handleRefresh = () => {
     refetch();
     toast.success("Flux actualisés");
   };
+
   const handleAddFeed = (feedData: any) => {
     console.log('Nouveau flux ajouté:', feedData);
     toast.success(`Flux "${feedData.name}" ajouté avec succès!`);
   };
+
   const handleOpenArticle = (article: NewsItem) => {
     setSelectedArticle(article);
     setIsArticleModalOpen(true);
   };
+
   const handleCloseArticleModal = () => {
     setIsArticleModalOpen(false);
     setSelectedArticle(null);
   };
+
   if (loading) {
-    return <div className="min-h-screen bg-background flex items-center justify-center">
+    return (
+      <div className="min-h-screen bg-background flex items-center justify-center">
         <div className="flex items-center gap-2">
           <Rss className="h-6 w-6 animate-spin text-primary" />
           <p>Chargement des articles...</p>
         </div>
-      </div>;
+      </div>
+    );
   }
-  return <div className="min-h-screen bg-background">
-      <Header searchQuery={searchQuery} onSearchChange={setSearchQuery} pinnedCount={pinnedCount} onAddFeedClick={() => setIsAddFeedModalOpen(true)} />
+
+  return (
+    <div className="min-h-screen bg-background">
+      <Header 
+        searchQuery={searchQuery} 
+        onSearchChange={setSearchQuery} 
+        pinnedCount={pinnedCount} 
+        onAddFeedClick={() => setIsAddFeedModalOpen(true)} 
+      />
       
       <main className="container mx-auto px-4 py-6">
         {/* Message pour les utilisateurs non connectés */}
         {!user}
 
         {/* Message pour les utilisateurs connectés sans articles suivis */}
-        {user && articles.length === 0 && <Card className="mb-6 border-yellow-200 bg-yellow-50">
+        {user && articles.length === 0 && (
+          <Card className="mb-6 border-yellow-200 bg-yellow-50">
             <CardContent className="pt-6">
               <div className="flex items-center gap-3">
                 <Rss className="h-5 w-5 text-yellow-600" />
@@ -108,7 +138,8 @@ const Index = () => {
                 </div>
               </div>
             </CardContent>
-          </Card>}
+          </Card>
+        )}
 
         {/* Debug info en développement */}
         {process.env.NODE_ENV === 'development'}
@@ -116,7 +147,13 @@ const Index = () => {
         <div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
           {/* Sidebar */}
           <div className={`lg:col-span-1 space-y-6 ${!showFilters && 'hidden lg:block'}`}>
-            <CategoryFilter categories={categories} selectedCategory={selectedCategory} onCategoryChange={setSelectedCategory} newsCount={articles.length} pinnedCount={pinnedCount} />
+            <CategoryFilter 
+              categories={categories} 
+              selectedCategory={selectedCategory} 
+              onCategoryChange={setSelectedCategory} 
+              newsCount={articles.length}
+              pinnedCount={pinnedCount} 
+            />
             
             <div className="bg-card border rounded-lg p-4 space-y-3">
               <h3 className="font-semibold text-sm">Statistiques</h3>
@@ -125,10 +162,12 @@ const Index = () => {
                   <span className="text-muted-foreground">Articles non lus</span>
                   <Badge variant="outline">{articles.length}</Badge>
                 </div>
-                {user && <div className="flex justify-between">
+                {user && (
+                  <div className="flex justify-between">
                     <span className="text-muted-foreground">Épinglés</span>
                     <Badge variant="secondary">{pinnedCount}</Badge>
-                  </div>}
+                  </div>
+                )}
               </div>
             </div>
           </div>
@@ -146,30 +185,44 @@ const Index = () => {
               </div>
               
               <div className="flex items-center gap-2">
-                <Button variant="outline" size="sm" onClick={() => setShowFilters(!showFilters)} className="lg:hidden gap-2">
+                <Button 
+                  variant="outline" 
+                  size="sm" 
+                  onClick={() => setShowFilters(!showFilters)} 
+                  className="lg:hidden gap-2"
+                >
                   <Filter className="h-4 w-4" />
                   Filtres
                 </Button>
                 
-                <Button variant="outline" size="sm" onClick={handleRefresh} className="gap-2">
+                <Button 
+                  variant="outline" 
+                  size="sm" 
+                  onClick={handleRefresh} 
+                  className="gap-2"
+                >
                   <RefreshCw className="h-4 w-4" />
                   Actualiser
                 </Button>
               </div>
             </div>
             
-            {filteredNews.length === 0 && articles.length > 0 ? <div className="text-center py-12">
+            {filteredNews.length === 0 && articles.length > 0 ? (
+              <div className="text-center py-12">
                 <p className="text-muted-foreground text-lg">Aucun article trouvé avec ces filtres</p>
                 <p className="text-sm text-muted-foreground mt-2">
                   Essayez de modifier vos filtres ou votre recherche
                 </p>
-              </div> : filteredNews.length === 0 ? <div className="text-center py-12">
+              </div>
+            ) : filteredNews.length === 0 ? (
+              <div className="text-center py-12">
                 <Rss className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
                 <p className="text-muted-foreground text-lg">Aucun article non lu disponible</p>
                 <p className="text-sm text-muted-foreground mt-2 mb-4">
                   {user ? 'Bravo ! Tous vos articles sont lus ou suivez des flux RSS pour voir des articles ici' : 'Aucun article public disponible pour le moment'}
                 </p>
-                {user && <div className="flex gap-2 justify-center">
+                {user && (
+                  <div className="flex gap-2 justify-center">
                     <Link to="/feeds">
                       <Button variant="outline">
                         Gérer les flux
@@ -179,18 +232,44 @@ const Index = () => {
                       <Plus className="h-4 w-4 mr-2" />
                       Ajouter un flux
                     </Button>
-                  </div>}
-              </div> : <div className="space-y-4">
-                {filteredNews.map(item => <NewsCard key={item.id} news={item} onTogglePin={togglePin} onMarkAsRead={markAsRead} onDelete={deleteArticle} onOpenArticle={handleOpenArticle} />)}
-              </div>}
+                  </div>
+                )}
+              </div>
+            ) : (
+              <div className="space-y-4">
+                {filteredNews.map(item => (
+                  <NewsCard 
+                    key={item.id} 
+                    news={item} 
+                    onTogglePin={togglePin} 
+                    onMarkAsRead={markAsRead} 
+                    onDelete={deleteArticle} 
+                    onOpenArticle={handleOpenArticle} 
+                  />
+                ))}
+              </div>
+            )}
           </div>
         </div>
       </main>
 
       {/* Modals */}
-      {user && <AddFeedModal isOpen={isAddFeedModalOpen} onClose={() => setIsAddFeedModalOpen(false)} onAddFeed={handleAddFeed} categories={categories} />}
+      {user && (
+        <AddFeedModal 
+          isOpen={isAddFeedModalOpen} 
+          onClose={() => setIsAddFeedModalOpen(false)} 
+          onAddFeed={handleAddFeed} 
+          categories={categories} 
+        />
+      )}
 
-      <ArticleModal isOpen={isArticleModalOpen} onClose={handleCloseArticleModal} article={selectedArticle} />
-    </div>;
+      <ArticleModal 
+        isOpen={isArticleModalOpen} 
+        onClose={handleCloseArticleModal} 
+        article={selectedArticle} 
+      />
+    </div>
+  );
 };
-export default Index;
+
+export default Index;