{listArticle.feed_title || 'Article'}
++ , {readingTimeLabel(listArticle.reading_time)} de lecture +
+diff --git a/web/src/App.tsx b/web/src/App.tsx index 36c3a6f..5d5e254 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,4 +1,5 @@ -import { lazy, Suspense, useEffect } from 'react'; +import { Suspense, useEffect } from 'react'; +import { lazyNamed } from './lib/lazy'; import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useAuthStore, clearUserData } from './stores/authStore'; @@ -8,9 +9,9 @@ import { ProtectedRoute } from './components/ProtectedRoute'; import { UpdateToast } from './components/UpdateToast'; // Route-level code splitting: the reader app and the auth screens load separately. -const LoginPage = lazy(() => import('./pages/LoginPage').then((m) => ({ default: m.LoginPage }))); -const RegisterPage = lazy(() => import('./pages/RegisterPage').then((m) => ({ default: m.RegisterPage }))); -const RootLayout = lazy(() => import('./layouts/RootLayout').then((m) => ({ default: m.RootLayout }))); +const LoginPage = lazyNamed(() => import('./pages/LoginPage'), 'LoginPage'); +const RegisterPage = lazyNamed(() => import('./pages/RegisterPage'), 'RegisterPage'); +const RootLayout = lazyNamed(() => import('./layouts/RootLayout'), 'RootLayout'); const queryClient = new QueryClient({ defaultOptions: { diff --git a/web/src/components/ArticleCard.tsx b/web/src/components/ArticleCard.tsx index 6d285ee..2c3ffa9 100644 --- a/web/src/components/ArticleCard.tsx +++ b/web/src/components/ArticleCard.tsx @@ -91,7 +91,7 @@ function ArticleCardImpl({ article, index, isCurrent, onOpen, onToggleRead, onTo {!article.is_read && (
diff --git a/web/src/components/SearchBox.tsx b/web/src/components/SearchBox.tsx deleted file mode 100644 index cde3b03..0000000 --- a/web/src/components/SearchBox.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { forwardRef, useEffect, useState } from 'react'; - -interface SearchBoxProps { - onSearch: (query: string) => void; -} - -/** - * Owns the raw input value so typing only re-renders this box; the list - * receives the debounced query. - */ -export const SearchBox = forwardRef{user?.email ?? 'Compte'}
-+
{user?.is_admin ? 'Administrateur' : 'Lecteur'}
{listArticle.feed_title || 'Article'}
++ , {readingTimeLabel(listArticle.reading_time)} de lecture +
+Par {listArticle.author}
} + {listArticle.author &&Par {listArticle.author}
} - {/* AI digest */} -{summaryError}
} - > - )} -{summaryError}
} +- Ce flux ne publie qu’un titre. {listArticle.url && 'Ouvrez l’article original pour le lire en entier.'} -
+Ce flux ne publie que le titre de l’article.
) ) : isError ? ( -Impossible de charger l’article.{' '} -
{searching ? 'Recherche' : 'Édition du jour'}
-
- {new Date().toLocaleDateString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long' })}
- {!searching && !favorites && (
- · {unreadTotal} non lu{unreadTotal > 1 ? 's' : ''}
- )}
+
+ {unreadTotal === 0
+ ? 'Tout est lu'
+ : `${unreadTotal} article${unreadTotal > 1 ? 's' : ''} non lu${unreadTotal > 1 ? 's' : ''}`}
{heading}
+ {!favorites && (
+